Kotlin笔记04(集合,Lambda表达式)

  1. 1. 集合的创建与遍历
    1. 1.1. List数组
    2. 1.2. Set集合
    3. 1.3. Map集合
  2. 2. 集合的函数式api
    1. 2.1. Lambda表达式
    2. 2.2. maxBy函数
    3. 2.3. 结合maxBy,Lambda定义,还原简化过程
    4. 2.4. map函数
    5. 2.5. filter函数
    6. 2.6. any函数
    7. 2.7. all函数
  3. 3. Java函数式API的使用

Kotlin的集合创建也是相当简单的。集合主要就是List和Set,Map这些的。

集合的创建与遍历

List数组

java的List

1
2
3
4
5
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
list.add("Pear");

当然kotlin也是可以这么做的

1
2
3
4
5
val list = ArrayList<>()
list.add("Apple")
list.add("Banana")
list.add("Orange")
list.add("Pear")

这么多代码,很明显不是kotlin的作风,当然可以进行简化

1
2
3
4
5
val list2 = listOf("Apple","Banana","Orange","Pear","Grape")
//for in的方式可以遍历这个数组
for(fruit in list2){
println(fruit)
}

listOf方法创建的是不可变的集合,需要可变的集合使用mutableListOf()

1
2
val list3 = mutableListOf("Apple","Banana","Orange","Pear","Grape")
list3.add("watermalon")

Set集合

和List一样

1
2
3
4
//和List集合几乎一样。创建集合方式变成了setOf和mutableSetOf
//Set集合的底层使用的是hash映射机制存储的,无法保证有序
val set1 = setOf("Apple","Banana","Orange","Pear","Grape")
val set2 = mutableSetOf("Apple","Banana","Orange","Pear","Grape")

Map集合

传统方式,Kotlin不推荐

1
2
3
val map1 = HashMap<String,Int>()
map1.put("Apple",1)
map1.put("Banana",2)

kotlin推荐的方式

1
2
3
val map1 = HashMap<String,Int>()
map1["Orange"] = 3
val num = map1["Orange"]

简化方式

1
2
3
4
5
val map2 = mapOf(
"Apple" to 1,
"Banana" to 2,
"Orange" to 3
)

这里的to看似是关键字进行关联,实际上to不是关键字,而是infix函数,后面可以自己写类似to的infix函数。也可以自己实现to的方式。

for-in遍历map集合

1
2
3
for((fruit,number) in map2){
println("$fruit 数量 $number")
}

集合的函数式api

Lambda表达式

lambda表达式的语法结构:

1
{ 参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}

首先外层大括号,如果有参数传入lambda表达式中,我们需要声明参数列表,参数列表之后 ->符号,表示参数列表的结束以及函数体的开始,函数体可以写任意行代码,并以最后一行代码会作为lambda表达式的返回值。

maxBy函数

从一个字符串数组当中找出最长的字符串。

第一时间想到的实现方法是:

1
2
3
4
5
6
7
8
val list2 = listOf("Apple","Banana","Orange","Pear","Grape")
var maxLengthFruit = ""
for(fruit in list2){
if(fruit.length > maxLengthFruit.length){
maxLengthFruit = fruit
}
}
println("max length fruit is " + maxLengthFruit)

如果用上集合的函数式api,可以让这件事变得更加简洁容易

1
2
3
val list = listOf("Apple","Banana","Orange","Pear","Grape")
val maxLenFruit = list.maxBy { it.length }
println(maxLenFruit)

结合maxBy,Lambda定义,还原简化过程

  1. 可以不用专门定义lambda

    1
    list.maxBy({fruit:String -> fruit.length})
  2. Kotlin规定当Lambda参数,(即{fruit:String -> fruit.length})是函数最后一个参数时,可以把Lambda放在括号外面

    1
    list.maxBy(){fruit:String -> fruit.length}
  3. 如果Lambda是函数的唯一一个参数,可以省略括号

    1
    list.maxBy{fruit:String -> fruit.length}
  4. 利用kotlin的类型推到机制,Lambda中的参数列表,大多数情况不用声明参数类型

    1
    list.maxBy{fruit -> fruit.length}
  5. 当只有一个参数时,可以不写参数名。可以用it关键字代替

    1
    list.maxBy{it.length}

map函数

map即映射,他可以将每个元素映射成另一个值

1
val newList = list.map{it.toUpperCase()} //全部大写

filter函数

filter函数,就是过滤

1
val newlist2 = list.filter { it.length <= 5 }.map{it.toLowerCase()}

any函数

any用于判断集合中是否至少存在一个元素满足条件。

1
val anyResult = list.any { it.length <= 5 }

all函数

all用于判断集合中是否所有元素满足条件

1
val allResult = list.all { it.length <= 5 }

Java函数式API的使用

Kotlin中调用一个java方法,并且该方法接受一个java单抽象方法接口函数,就可以用函数式API

单抽象方法接口: 接口中只有一个待实现的方法

比如:Java中的子线程创建

1
2
3
4
5
6
new Thread(new Runnable(){
@override
public void run(){
System.out.println("Thread is running")
}
}).start();

Kotlin当中就是这么写的

1
2
3
4
5
Thread(object:Runnable{
override fun run() {
println("Thread is running")
}
}).start()

由于kotlin舍去了new,因此匿名类实例的时候不能用new了,而是改用object。

进一步精简:

1
2
3
4
//如果接口中只有一个待实现方法,可以省略
Thread({
println("Thread is running")
}).start()

再利用上面的简化方法

1
Thread{println("Thread is running")}.start()

其实kotlin提供了一个更简单的方法

1
thread{println("Thread is running")}

这个thread可选参数有很多,可以自己点进去看,这个方法的实现很简单。完全可以不用说,看一眼他的实现就能明白怎么用的。