文章目录
一丶高阶函数
package chapter01
// region + 折叠
fun main(){
/*高阶函数的调用*/
//如果括号里的函数类型作为最后一个参数,可移到括号外面
//it 是Lambda的特性
intArray.forEach(){
println("Hello $it")
}
//等价于
intArray.forEach{
println("Hello $it")
}
}
// endregion
/*高阶函数*/
// region + 折叠
//特征一: block:()->Unit —— 参数包含函数类型
//特征二:返回值为函数类型
fun needsFunction(block:()->Unit){
block()
}
// endregion
// 常见的高阶函数一:
//IntArray.forEach —— 扩展方法
//action:(Int) -> Unit —— 接收函数类型作为参数
inline fun IntArray.forEach(action:(Int) -> Unit):Unit{
//action(element) —— 调用函数action
for(element in this) action(element)
}
// 常见的高阶函数二:
//R —— 返回值元素类型
//transform:(Int)->R —— 接收函数类型作为参数
inline fun <R>IntArray.map(transform:(Int)->R):List<R>{
//transform —— 进一步传递 transform
return mapTo(ArrayList<R>(size),transform)
}
二丶内联函数
package chapter02
fun main(){
/*内联函数的概念*/
//通过 inline标记
val ints = intArrayOf(1,2,3,4)
ints.forEach {
println("Hello $it")
}
/*内敛高阶函数的return*/
val ints = intArrayOf(1,2,3,4)
ints.forEach {
//return@forEach 跳出这一次内联函数调用 与 Java Continue 一样
if (it == 3)return@forEach
println("Hello $it")
}
/*non-local return*/
nonLocalReturn {
return //△表示:并不是退出Lambda表达式,而是从 外部 函数(main)返回
}
}
inline fun IntArray.forEach(action:(Int)->Unit):Unit{
for (element in this) action(element)
}
/*定义内联函数*/
inline fun hello(){
println("Hello")
}
/*non-local return*/
inline fun nonLocalReturn(block:()->Unit){
block()
}
/*non-local return*/
//不合法的情况
inline fun Runnable(block: () -> Unit):Runnable{
return object :Runnable{
override fun run() {
//不合法处
原因:
1、有可能存在不合法的 non-local return
2、因为 block 的调用处与定义处不在同一个调用上下文
//其实return 的是 run 而不是Runnable
block()
}
}
}
//解决方法一:
//禁止 non-local return
inline fun Runnable(crossinline block: () -> Unit):Runnable{
return object :Runnable{
override fun run() {
block()
}
}
}
//解决方法二:
//禁止函数参数被内敛
inline fun Runnable(noinline block: () -> Unit):Runnable{
return object :Runnable{
override fun run() {
block()
}
}
}
/*内联属性*/
//含义: 没有 backing-field 的属性 getter/setter 可以被内联
//举例:
var pocket.Double = 0.0
var money.Double
inline get() = pocket
inline set(value){
pocket = value
}
/*内联函数的限制*/
//1、public/protected 的内联方法只能访问对应类的 public 成员
//2、内联函数的内联参数不能被存储(赋值给变量)
//3、内联函数的内联函数参数只能传递给其他内联函数参数
三丶几个有用的高阶函数
package chapter03
import java.io.File
fun main(){
val person = Person("benny",20)
//let举例:返回表达式结果
// '::' 表示把一个方法当做一个参数,传递到另一个方法中进行使用,通俗的来讲就是引用一个方法
person.let(::println)
//run举例:返回表达式结果
person.run(::println)
//also举例:返回Receiver
val person2 = person.also {
it.name = "hhh"
}
//apply举例:返回Receiver
val person3 = person.apply {
name = "xxx"
}
//use举例:自动关闭资源
File("build.gradle").inputStream().reader().buffered()
.use {
println(it.readLine())
}
}
/*几个有用的函数*/
// let、run、also、apply、use
//举例
class Person(var name:String,var age:Int){
}
四丶集合变化与序列
package chapter04
import java.lang.StringBuilder
fun main(){
/*filter 变换(序列)*/
//Java版本:
list.stream()
.filter(e->e%2 == 0)
// 等价于
//kotlin版本一:
//asSequence()转换为懒汉式
list.asSequence()
.filter{it % 2 == 0}
//kotlin版本二:
list.filter{it % 2 == 0}
/*map 变换*/
//Java版本:
list.stream()
.filter(e->e%2 == 0)
//kotlin版本一:
list.map{it*2+1}
//kotlin版本二:
list.asSequence()
.map{it*2+1}
/*flatMap变换*/
// flatMap概念:用一个元素映射成一个集合,再把这个集合拼接起来得到新的集合
// Map概念:把里面的元素映射成新的元素,那么这些元素组成的集合就成为Map集合
// 写法一:
val list = listOf(1,2,3,4)
list.flatMap {
(0 until it)
}
.joinToString().let(::println)
// 写法二:
list.asSequence() //将集合变成一个序列
.flatMap {
(0 until it).asSequence() //结果也应该要变成一个序列
}
.joinToString().let(::println)
/*集合的聚合操作举例*/
//1、sum —— 所有元素求和
//2、reduce 将元素一次按规则聚合,结果于元素类型一致
//3、fold —— 给定初始化值,将元素按规则聚合,结果与初始化值类型一致
/*fold操作*/
//acc —— 每一次拼接后的结果
//i —— 遍历的list集合里的每一个元素
list.fold(StringBuilder()){
//acc.append(i) —— 返回值类型为StringBuilder,作为下一个元素的 acc
acc,i -> acc.append(i)
}
/*恶汉式举例*/
//概念:会分别在filter里马上遍历List集合,在往下走到map集合时就会马上调用list进行映射,再到forEach
//区别:filter{}与map{}还有flatMap{}会立即调用
//代码运行结果:0 1 2 3 4 0 1 2 3 4 5 6 7 8
list.filter {
it % 2 == 0
}.map {
it * 2 + 1
}.flatMap {
0 until it
}.forEach(::println)
/*懒序列举例:*/
//概念:集合里的元素只有通过了一个才能继续往下走
//区别:forEach 时才会调用filter{}与map{}还有flatMap{}
//forEach —— 在这里就像是一个钥匙,如果没有这句代码打开水管,那上面的三个函数就像被堵住一样都不会调用
//代码运行结果:0 1 2 3 4 0 1 2 3 4 5 6 7 8
list.asSequence()
.filter {
it % 2 ==0
}.map {
it *2 +1
}.flatMap {
(0 until it).asSequence()
}.forEach(::println)
}
五丶SAM 转换
package chapter05
fun main(){
//Java中的lambda表达式是没有自己的类型的,而且只能接口里只能有一个方法
//kotlin实际上时创建一个 Runnable 包装了一下Lambda,并非直接转换
}
六丶案例:统计字符个数
package chapter06
import java.io.File
fun main(){
//打开文件build.gradle,阅读文本,string 类型
File("build.gradle").readText()
.toCharArray() //把它们char类型数组
.filter { !it.isWhitespace() } //过滤空白字符
.groupBy { it } //it 是charArray里的每一个字符,通过it来分组,得到key 就是 char
.map {
it.key to it.value.size //映射
}.let {
print(it)
}
}