【5】Kotlin基础——集合与Lambda编程

提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方,欢迎各位在评论中指出。

文章目录

  • 一、集合
    • 1.1List集合
      • 1.1.1 不可变集合listOf()
      • 1.1.2 可变集合mutableListOf()
    • 1.2 Set集合
    • 1.3 Map集合
  • 二、Lambda编程
    • 2.1 Lambda表达式
    • 2.2 常见的函数式API

一、集合

在开始了解Lambda编程前,我们需要先学习一些与集合相关的知识。Kotlin语言提供了丰富的集合类,包括但不限于以下几种:

  1. List(列表):有序可重复的集合,可以通过索引访问元素。List是一个只读的集合,它只能访问集合中的元素,不能对元素进行修改操作。
  2. Set(集合):无序不可重复的集合,不能通过索引访问元素。Set同样是一个只读的集合,它只能访问集合中的元素,不能进行修改操作。
  3. Map(映射):以键值对形式存储元素的只读集合,每个键都是唯一的。

与上面的三种只读集合不同,MutableList、MutableSet和MutableMap集合允许对集合中的元素进行修改

1.1List集合

List是一种有序且可重复的集合,我们可以通过索引访问集合中某个特定的元素,所以List集合中的元素是可以重复的

1.1.1 不可变集合listOf()

如果我们想创建一个包含许多水果名称的集合,你可能会想到以下代码:

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集合是一个只读集合。你只能访问集合中的元素,而不能对集合中的元素进行修改。

1.1.2 可变集合mutableListOf()

需要注意的是,Kotlin语言在不可变方面的约束很严格:

  • listOf( ) 方法创建的的是一个只读的List集合。只能对该集合内的元素进行读取,无法对其进行修改。
  • mutableListOf( ) 方法创建的是一个可变的List集合,我们可以对集合中的元素进行修改。
fun main() {
    //通过mutableListOf()创建一个可变的集合并对其进行初始化
    val list = mutableListOf("Apple", "Banana", "Orange", "Pear", "Grape")
    //向该集合中添加元素
    list.add("Watermelon")
    for (fruit in list) {
        println(fruit)
    }
}

1.2 Set集合

Set集合中的元素是无序且不可重复的,我们不能通过索引来访问指定元素。如果在Set集合中存放了多个相同的元素,则只会保留其中的一个

  • setOf( ) 方法创建的是一个只读的Set集合。只能对该集合内的元素进行读取,无法对其进行修改操作。
  • mutableSetOf( ) 方法创建的是一个可变的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")

1.3 Map集合

Map是一种 键值对形式的数据结构,因此在用法上和List、Set集合有较大不同。传统的Map用法是先创建一个HashMap实例,然后将一个个键值对数据添加到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编程

2.1 Lambda表达式

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 }

2.2 常见的函数式API

如果我们想将集合中的所有水果名都变为大写模式:

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。

  • any函数用来判断集合中是否至少存在一个满足指定条件的元素。
  • all函数用来判断集合中是否所有元素都满足指定条件。
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 

你可能感兴趣的:(奇妙的Kotlin之旅,kotlin,开发语言,android)