提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方,欢迎各位在评论中指出。
在开始了解Lambda编程前,我们需要先学习一些与集合相关的知识。Kotlin语言提供了丰富的集合类,包括但不限于以下几种:
与上面的三种只读集合不同,MutableList、MutableSet和MutableMap集合允许对集合中的元素进行修改。
List是一种有序且可重复的集合,我们可以通过索引访问集合中某个特定的元素,所以List集合中的元素是可以重复的。
如果我们想创建一个包含许多水果名称的集合,你可能会想到以下代码:
val list = ArrayList<String>()
list.add("Apple")
list.add("Banana")
list.add("Orange")
list.add("Pear")
list.add("Grape")
但是通过调用add()来初始化集合比较繁琐,Kotlin专门提供了listOf()方法来简化集合的初始化。我们可以仅通过一行代码就完成集合的初始化操作:
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
如果我们想遍历这个集合该怎么操作呢?我们可以使用for-in循环来进行遍历:
fun main() {
//通过listOf()创建一个只读集合并对其进行初始化
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
//使用for-in循环对其进行遍历(fruit表示集合中的各个元素)
for (fruit in list) {
println(fruit)
}
}
但需要注意的是,通过listOf()方法创建的List集合是一个只读集合。你只能访问集合中的元素,而不能对集合中的元素进行修改。
需要注意的是,Kotlin语言在不可变方面的约束很严格:
fun main() {
//通过mutableListOf()创建一个可变的集合并对其进行初始化
val list = mutableListOf("Apple", "Banana", "Orange", "Pear", "Grape")
//向该集合中添加元素
list.add("Watermelon")
for (fruit in list) {
println(fruit)
}
}
Set集合中的元素是无序且不可重复的,我们不能通过索引来访问指定元素。如果在Set集合中存放了多个相同的元素,则只会保留其中的一个。
// 通过setOf创建并初始化一个只读的Set集合
val set = setOf("apple", "banana", "orange")
// 遍历Set集合
for (item in set) {
println(item)
}
// 1.通过mutableSetOf()创建一个可变的Set集合 之后通过add()方法对其进行初始化
val mutableSet = mutableSetOf<String>()
mutableSet.add("apple")
mutableSet.add("banana")
mutableSet.add("orange")
// 2.或者在创建集合的同时就对其进行初始化
val mutableSet = mutableSetOf<String>("apple", "banana", "orange")
// 从Set集合中删除元素
mutableSet.remove("banana")
// 判断Set集合是否包含某元素
val containsItem = mutableSet.contains("apple")
println("Contains apple: $containsItem")
Map是一种
//创建一个由String和Int组成键值对的map集合
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)
虽然这种写法在Kotlin中是允许的,但是Kotlin语言不建议使用put()和get()方法对Map进行增加和读取操作。而是更推荐使用一种类似于数组下标的语法结构。例如,向Map中添加一条数据你可以这么写:
val map = HashMap<String, Int>()
// 向map中添加数据
map["Apple"] = 1
map["Banana"] = 2
//从map中读取数据
val AppleNumber = map["Apple"]
val BananaNumber = map["Banana"]
Kotlin也同样提供了 mapOf() 方法来创建一个只读的Map集合,mutableMapOf() 方法来创建一个可变的Map集合。
①mapOf( )方法:
fun main() {
//使用mapOf()创建并初始化一个只读的Map集合
val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
//遍历Map集合 并用(x,y)表示Map集合中的元素
for ((fruit, number) in map){
println("fruit is " + fruit + ", number is " + number)
}
}
在上面的代码中,我们先是通过mapOf()方法创建了一个Map集合,并在创建的时候就完成了集合内元素的初始化。然后我们遍历这个Map集合,并将Map中元素键值对的值声明到一对括号里(fruit, number)。当遍历Map集合时,每次遍历得到的元素的值就会赋值给fruit和number变量,我们就可以通过操作这两个变量实现对集合中的元素进行操作。
②mutableMapOf( )方法:
fun main() {
val map = mutableMapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
//Kotlin不推荐的写法(使用put和get方法)
map.put("Peach", 6)
val peach = map.get("Peach")
//Kotlin推荐的写法(使用类似下标的方式)
map["Watermelon"] = 7
val watermelon = map["Watermelon"]
for((fruit, number) in map) {
println("fruit is " + fruit + ", number is " + number)
}
}
在这段代码中我们通过mutableMapOf()方法创建了一个可变的Map集合,我们可以使用put()方法向该集合中添加元素或者使用get()方法从该集合中获取元素 (Kotlin不推荐);当然Kotlin更推荐我们使用类似下标的方式向该集合中添加或获取某个元素(Kotlin推荐)。
Lambda就是一小段可以作为参数传递的代码。我们在Lambda函数体中可以编写相应的逻辑代码,并且Lambda表达式中最后一行代码会作为返回值。Lambda表达式的示例代码如下:
参数名 参数类型 函数体
val sum = {x: Int, y: Int -> x + y }
println(sum(2,3))
——>输出5
接下来让我们来思考一个问题,如何在一个水果集合里面找到单词最长的那个水果?
//水果集合
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
//单词最长的水果
var maxLengthFruit = ""
//遍历水果集合
for (fruit in list){
//如果下一个水果的单词比maxLengthFruit长
if(fruit.length > maxLengthFruit.length){
//将其保存在maxLengthFruit中
maxLengthFruit = fruit
}
}
println("max length fruit is " + maxLengthFruit)
上面这段代码是很常规的写法,其实我们也可以使用Lambda函数对其进行简化:
val list = listOf("Apple","Banana","Orange","Pear","Grape","Watermelon")
val maxLengthFruit = list.maxBy{ it.length }
println("max length fruit is " + maxLengthFruit)
可能你看到这段代码会觉得很难理解,这是因为这段代码是由Lambda表达式简化而来的。maxBy( )方法的工作原理就是依据我们传入的条件来遍历集合,并从中找到该条件下的最大值。现在让我们来学习一下他的简化流程:
val list = listOf("Apple","Banana","Orange","Pear","Grape","Watermelon")
//Lambda表达式接收一个String类型的参数fruit,并返回它的字符串长度
参数名 参数类型 函 数 体
val lambda = { fuit: String -> fruit.length }
val maxLengthFruit = list.maxBy(lambda)
|
| simplify
|
V
我们可以不用专门定义一个Lambda变量,而是直接把Lambda表达式传给maxBy方法。
val maxLengthFruit = list.maxBy({ fuit: String -> fruit.length })
|
| simplify
|
V
当Lambda参数是方法的最后一个参数时,可以将Lambda表达式移到方法括号的外面。
val maxLengthFruit = list.maxBy() { fuit: String -> fruit.length }
|
| simplify
|
V
如果Lambda参数是方法的唯一一个参数的话,可以将方法的括号省略。
val maxLengthFruit = list.maxBy { fuit: String -> fruit.length }
|
| simplify
|
V
其实Lambda表达式中的参数大多数情况下不必声明参数类型。
val maxLengthFruit = list.maxBy { fruit, fruit.length }
|
| simplify
|
V
当Lambda表达式的参数中只有一个参数时,可以不用声明参数名,而是用it关键字进行代替。
// 遍历集合 找出长度最大的元素
val maxLengthFruit = list.maxBy { it.length }
如果我们想将集合中的所有水果名都变为大写模式:
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
// 遍历元素 并使用toUpperCase()方法将每一个元素转为大写字母
val newList = list.map { it.toUpperCase() }
for (fruit in newList) {
println(fruit)
}
}
如果我们只想保留5个字母以内的水果,则可以借助filter方法过滤特定元素:
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
先过滤出所有名称长度大于5的水果名 然后将其转为大写
val newList = list.filter { it.length <= 5 }.map { it.toUpperCase() }
for (fruit in newList) {
println(fruit)
}
}
any和all也是两种很常见的函数式API。
fun main() {
val list = listOf("Apple","Banana","Orange","Pear","Grape","Watermelon")
//list集合中是否存在满足字母长度<=5的水果
val anyResult = list.any { it.length <= 5 }
//list集合中是否所有水果字母长度都<=5
val allResult = list.all { it.length <= 5 }
println("anyResult is :" + anyResult + ",allResult is :" + allResult)
}
——>输出
anyResult is: true, allResult is: false