Kotlin:Lambda编程(补档)
Kotlin: Lambda编程(补档)
List集合
由于逐项初始化集合的方式比较繁琐,kotlin专门提供了一个内置的listOf()函数用来简化初始化集合的过程,如下代码:
1 | val list = listOf("Apple" , "Banana" , "Orange" , "Pear" , "Grape") |
尝试用 for-in 循环来遍历这个水果集合:
1 | fun main() { |
注意:listOf定义的集合是一个不可变的集合(只读),如果要创建一个可变的集合,需用关键字mutableListOf
1 | val list = mutableListOf("Apple" , "Banana" , "Orange" , "Pear" , "Grape") |
修改可变的list集合:
1 | fun main() { |
Set集合
Set集合的用法与list集几乎一模一样,只是将定义集合的方式换成了setOf()和mutableSetOf()函数而已,大致代码如下
1 | fun main() { |
需要注意:Set集合底层是使用hash映射机制来存放数据的,因此集合中的元素无法保证顺序。这是Set集合和List集合最大的不同之处。
Map集合
Map集合是一种键值对形式的数据结构,因此在用法上和list、Set有比较大的不同。传统的Map用法是先创建一个HashMap的实例
,然后将一个个键值对数据添加到Map中。如下代码:
1 | val map = HashMap<String , Int> () |
以上的写法比较接近Java中的语法,也比较好理解。但在Kotlin中推荐使用一种类似于数组下标的语法结构,如下代码:
1 | map["Apple"]=1 |
而从Map中读取一条数据就可以这样写:
1 | val number = map["Apple"] |
因此,上述代码经过优化后就可以变成如下形式:
1 | val map = HashMap <String , INt>() |
当然,这仍然不是最简便的写法,在Kotlin中,可以写如下代码:
1 | val map = mapOf("Apple" to 1 , "Banana" to 2 , "Orange" to 3 , "Pear" to 4 , "Grape" to 5) |
注:这里用于关联键值对的“to"不是一个关键字,而是一个infix函数。
Map集合中的数据也可以使用 for-in 循环进行遍历,如下代码:
1 | fun main(){ |
集合的函数式API
Lamda的定义
Lambda就是一小段可以作为参数传递的代码。【Kotlin中不对“一小段代码”究竟有多小进行限制,但是不建议在Lambda表达式中编写太长的代码,否则可能会影响代码的可读性】
Lambda表达式的语法结构:
{参数名1 : 参数类型 , 参数名2 : 参数类型 -> 函数体}
这是Lambda表达式最完整的语法结构定义。
- 最外层是一对大括号
- 如果有参数传入到Lambda表达式中,我们还需要声明参数列表
- 参数列表的结尾用一个 -> 符号,表示参数列表的结束以及函数体的开始
- 函数体中可以编写任意行代码,最后一行会自动作为Lambda表达式的返回值
在很多情况下,我们无需使用Lambda表达式的完整语法结构,而是有很多简化的写法,以下为一步步简化的过程
- 最基本的Lambda写法:
1 | val list = listOf("Apple" , "Banana" , "Orange" , "Pear" , "Grape" , "Watermelon") |
代码分析:1.fruit : String : 向 lambda中传入了参量 fruit,这是最后一个参量,因此lambda默认返回值即为 fruit
代码分析:2.fruit.length:这部分是我们定义的lambda的函数体,maxBy函数的工作原理是按我们传入的条件来遍历集合,从而找到该条件下的最大值。我们希望找到名字最长的fruit,因此传入了fruit.length
- 简化:我们并不需要专门定义一个lambda变量,而是可以直接将lambda表达式传入maxBy函数当中:
1 | val maxLengthFruit = list.maxBy({fruit : String -> fruit.length }) |
- 简化:Kotlin规定,当Lambda参数是函数的最后一个参数时,可以将Lambda表达式移到函数括号的外面:
1 | val maxLengthFruit = list.maxBy(){fruit : String -> fruit.length } |
- 简化:如果Lambda参数是函式的唯一一个参数时,可以将函数的括号省略:
1 | val maxLengthFruit = list.maxBy{fruit : String -> fruit.length } |
- 简化:由于Kotlin拥有出色的类型推导机制,Lambda表达式中的参数列表其实在大多情况下不必声明参数类型:
1 | val maxLengthFruit = list.maxBy{fruit -> fruit.length } |
- 简化:当Lambda表达式的参数列表中只有一个参数时,不必声明参数名,可以直接用it关键字来替代:
1 | val maxLengthFruit = list.maxBy{it.length } |
因此,原程序代码可以如下编制:
1 | val list = listOf("Apple" , "Banana" , "Orange" , "Pear" , "Grape" , "Watermelon") |
集合中常用的函数式API
map函数
map函数是最常用的一种函数式API,它用于将集合中的每个元素都映射成一个另外的值,映射的规则在Lambda表达式中指定,最终生成一个新的集合。例如,我们希望让所有的水果名都变成大写模式,代码如下:
1 | fun mian () { |
map函数的功能非常强大,它可以按照我们的需求对集合中的元素进行任意的映射转换,只要在Lambda表达式中编写所需要的逻辑即可。
filter函数
filter函数用于过滤集合中的数据,它可以单独使用,也可以同map函数一起使用
例如,我们只想保留5个字母以内的水果,就可以借助filter函数来实现,代码如下:
1 | fun main() { |
any 和 all 函数
- any函数用于判断集合中是否至少存在一个元素满足指定条件
- all用于判断集合中是否所有元素都满足判定条件
示例代码如下:
1 | fun main() { |
传回给anyResult的值是Boolean型
JAVA函数式API的使用
Kotlin调用Java方法时也可以使用函数式API,但是有一定限制。如果我们在Kotlin代码中调用了一个Java方法,并且该方法接受一个Java单抽象方法接口参数,就可以使用函数式API。
具体内容,参考《第一行代码 Android》(第三版)P69~P70 :2.6.3 Java函数式API的使用