目录
2.6 Lambda 编程
可能很多 Java 程序员对于 Lambda 编程还比较陌生,但其实这并不是什么新鲜的技术。许多现代高级编程语言在很早之前就开始支持 Lambda 编程了,但是 Java 却直到 JDK 1.8 之后才加入了 Lambda 编程的语法支持。因此,大量早期开发的 Java 和 Android 程序其实并未使用 Lambda 编程的特性。
而 Kotlin 从第一个版本开始就支持了 Lambda 编程,并且 Kotlin 中的 Lambda 功能极为强大,我甚至认为 Lambda 才是 Kotlin 的灵魂所在。不过,本章只是 Kotlin 的入门章节,我不可能在这短短一节里就将 Lambda 的方方面面全部覆盖。因此,这一节我们只学习一些 Lambda 编程的基础知识,而像高阶函数、DSL 等高级 Lambda 技巧,我们会在本书的后续章节慢慢学习。
2.6.1 集合的创建与遍历
集合的函数式 API 是用来入门 Lambda 编程的绝佳示例,不过在此之前,我们得先学习创建集合的方式才行。
传统意义上的集合主要就是 List 和 Set,再广泛一点的话,像 Map 这样的键值对数据结构也可以包含进来。List、Set 和 Map 在 Java 中都是接口,List 的主要实现类是 ArrayList 和 LinkedList,Set 的主要实现类是 HashSet,Map的主要实现类是 HashMap,熟悉 Java 的人对这些集合的实现类一定不会陌生。
现在我们提出一个需求,创建一个包含许多水果名称的集合。如果是在 Java 中你会怎么实现? 可能你首先会创建一个 ArrayList 的实例,然后将水果的名称一个个添加到集合中。当然,在 Kotlin 中也可以这么做:
fun main(){
val list = ArrayList<String>()
list.add("Apple")
list.add("Banana")
list.add("Orange")
list.add("Pear")
list.add("Grape")
}
但是这种初始化集合的方式比较烦琐,为此 Kotlin专门提供了一个内置的 listOf() 函数来简化 初始化集合的写法,如下所示:
val list = listOf("Apple","Banana","Orange","Pear","Grape")
可以看到,这里仅用一行代码就完成了集合的初始化操作。
还记得我们在学习循环语句时提到过的吗?for-in 循环不仅可以用来遍历区间,还可以用来遍 历集合。现在我们就尝试一下使用 for-in 循环来遍历这个水果集合,在 main() 函数中编写如 下代码:
fun main(){
val list = listOf("Apple","Banana","Orange","Pear","Grape")
for (fruit in list){
println(fruit)
}
}
运行一下代码,结果如 图2.23 所示。
![](https://i-blog.csdnimg.cn/blog_migrate/40f0b4b858fc6133742719102a4b907b.png)
不过需要注意的是,listOf() 函数创建的是一个不可变的集合。你也许不太能理解什么叫作不 可变的集合,因为在 Java 中这个概念不太常见。不可变的集合指的就是该集合只能用于读取, 我们无法对集合进行添加、修改或删除操作。
至于这么设计的理由,和 val 关键字、类默认不可继承的设计初衷是类似的,可见 Kotlin 在不可变性方面控制得极其严格。那如果我们确实需要创建一个可变的集合呢?也很简单,使用 mutableListOf() 函数就可以了,示例如下:
fun main(){
val list = mutableListOf("Apple","Banana","Orange","Pear","Grape")
list.add("Watermelon")
for (furit in list){
println(furit)
}
}
这里先使用 mutableListOf() 函数创建一个可变的集合,然后向集合中添加了一个新的水 果,最后再使用 for-in 循环对集合进行遍历。现在重新运行一下代码,结果如 图2.24 所示。
![](https://i-blog.csdnimg.cn/blog_migrate/3a6e02f65ecee75354c124c4a417acae.png)
可以看到,新添加到集合中的水果已经被成功打印出来了。
前面我们介绍的都是 List 集合的用法,实际上 Set 集合的用法几乎与此一模一样,只是将创建集合的方式换成了 setOf() 和 mutableSetOf() 函数而已。大致代码如下:
fun main(){
val set = setOf("Apple","Banana","Orange","Pear","Grape")
for (furit in set){
println(furit)
}
}
需要注意,Set 集合中是不可以存放重复元素的,如果存放了多个相同的元素,只会保留其中一份,这是和 List 集合最大的不同之处。当然这部分知识属于数据结构相关的内容,这里就不展 开讨论了。
最后再来看一下 Map 集合的用法。Map 是一种键值对形式的数据结构,因此在用法上和List、 Set 集合有较大的不同。传统的 Map 用法是先创建一个 HashMap 的实例,然后将一个个键值对数据添加到 Map 中。比如这里我们给每种水果设置一个对应的编号,就可以这样写:
fun main(){
val map = HashMap<String,Int>()
map.put("Apple",1)
map.put("Banana",2)
map.put("Orange",3)
map.put("Pear",4)
map.put("Grape",5)
}
我之所以先用这种写法,是因为这种写法和 Java 语法是最相似的,因此可能最好理解。但其实在Kotlin中并不建议使用 put() 和 get()