不知不觉间,2月份就过去,也就是说2018年已经过去了六分之一,再细想真可怕。

今天继续Kotlin的学习,主要从lambda的历史,定义,和集合的函数API,以及推荐使用的withapply两个常用的函数。

lambda表达式

Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包。在Java8中,加入了lambda表达式,可以简化代码,方便开发者开发更高效的代码。

其表达式很简单:

1
(argument) -> (body)

lambda编码了一小块你可以用作一个值进行传递的行为。它可以被独立的声明并存储在一个变量中。但是更常见的是,当它被传递给一个函数时直接声明。在Kotlin中,一个lambda表达式往往被一个大括号所包围,如下段代码:

1
val sum = { x: Int, y: Int -> x + y }

用java实现可能如下:

1
2
3
int sum(int x,int y) {
return x + y;
}

为了更好简化代码,lambda表达式也是越来越简短,我们就用点击一个button时,打印对应的view的id,如代码如下:

1
2
3
4
btn?.setOnClickListener({ v ->
print(v.id)

})

lambda表达式作为参数时,且是参数列表里的最后一个参数,可以把{}放到外面:

1
2
3
btn?.setOnClickListener(){ v ->
print(v.id)
}

当lambda是函数的唯一参数时,你也可以删掉空的圆括号:

1
2
3
btn?.setOnClickListener{ v ->
print(v.id)
}

使用

集合的函数式API

函数式风格代码,简化了代码,使得代码不被各种逻辑分离,其中集合也提供一些常见的函数式API,使得我们的开发事半功倍。

filter和map

记得之前学习RxJava时有这两个函数,在Kotlin中其实也很类似,可以参考RxJava来理解这两个函数(filter, map)。

1
2
val nums = listof(1, 4, 8, 9)
list.filter{ it % 2 == 0} // 偶数

打印结果是

1
2

[2, 4]

filter里面实际上返回的是个boolean值,只有返回值为true才会被留下,当然返回值依然是之前的类型(如例子中的list返回依然是list)

1
2
val nums = listof(1, 2, 4, 5)
list.map{ it *it } //

打印结果是

1
2

[1, 4, 16, 25]

预言:all, any, count和find

all是所有都满足指定条件(预言)才返回true,any则判断至少有一个满足条件,find则查找第一个指定条件,count表示满足预言的元素个数。

groupBy

将指定维度的条件分组,将指定维度下的相同元素进行分组,返回是map类型

with和apply函数

1
2
3
4
5
6
7
8
fun alphabet(): String {
val result = StringBuilder()
for (letter in 'A'..'Z') {
result.append(letter)
}
result.append("\nNow I know the alphabet!")
return result.toString()
}

由于在代码大量使用result, 写起来很是麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
fun alphabet(): String {
val stringBuilder = StringBuilder()

return with(stringBuilder) { // 1 在你调用的方法中制定接收器的值
for (letter in 'A'..'Z') {
this.append(letter) // 2 通过显式的“this”调用接收器值的方法
}

append("\nNow I know the alphabet!") // 3 调用方法,忽略“this”

this.toString() // 4 从lambda中返回值
}
}

文中的this都可以都可以忽略,不过有时需要alphabet内写这个类的this对象时,可以声明变量来实现。

apply基本上使用和with类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
fun alphabet(): String {
val stringBuilder = StringBuilder()

return StringBuilder().apply { // 1 在你调用的方法中制定接收器的值
for (letter in 'A'..'Z') {
this.append(letter) // 2 通过显式的“this”调用接收器值的方法
}

append("\nNow I know the alphabet!") // 3 调用方法,忽略“this”

// 4 从lambda中返回值
}.toString()
}

二者的不同主要在返回值,用with返回值不是stringBuilder自己的类型,而apply返回则仍然是StringBuilder类型。