Kotlin的lambda函数式编程
lambda函数式编程
lambda表达式结构是:{参数名: 参数类型, 参数名: 参数类型 … -> 函数体}(参数1, 参数2, …)
如我们要找出字符串数组的最长的那个单词,可以写成:
1 | fun main() { |
如果我们想写成lambda表达式的话,可以用$\texttt{maxBy}$这个函数,该函数工作原理是接收一个lambda表达式,根据传入的条件来找到最大值。那么上述的代码就可以写成:
1 | val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") |
然后对他进行简化,首先$\texttt{maxBy}$里面可以直接传lambda参数:
1 | val maxLengthFruit = list.maxBy({fruit: String -> fruit.length}) |
然后$\texttt{Kotlin}$还规定,当lambda参数是函数最后一个参数时,可以将{}放在()后面:
1 | val maxLengthFruit = list.maxBy(){fruit: String -> fruit.length} |
如果lambda参数是函数唯一参数的话,还可以直接省略():
1 | val maxLengthFruit = list.maxBy{fruit: String -> fruit.length} |
然后加上$\texttt{Kotlin}$的优秀推导类型的机制,可以直接省略类型,然后当参数只有一个时,可以直接用it
代替:
1 | val maxLengthFruit = list.maxBy{it.length} |
这样一步步推导就可以推导出最简形式了。
map函数
$\texttt{map}$函数非常常用,可以把集合的每个元素都映射成另一个值,规则则是由接受的lambda表达式决定。比如我们要将水果名变成大写:
1 | val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") |
运行结果就是:
1 | APPLE |
filter函数
$\texttt{filter}$函数可以过滤集合中的数据,也同样接受lambda表达式。,可以搭配$\texttt{map}$函数使用:
1 | val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") |
运行结果就是PEAR
了。
Java函数式API使用
当我们用Kotlin调用Java方法时,如果这个方法只接受一个Java单抽象方法接口参数就可以换成函数式API。单抽象方法接口指这个接口中只有一个待实现的方法。比如线程中的$\texttt{Runnable}$接口,就只有一个run()
方法:
1 | public interface Runnable { |
我们在$\texttt{Thread}$类中接受一个$\texttt{Runnable}$参数:
1 | new Thread(new Runnable() { //使用匿名内部类 |
在Kotlin中,没有new这个关键字,改成了object关键字:
1 | Thread(object : Runnable { |
然后这个Thread类的写法符合函数API的形式,故可以简化:
1 | Thread(Runnable { |
然后如果Java方法参数列表只有一个Java单抽象方法接口参数,可以直接对接口名省略:
1 | Thread({ |
然后根据上面的简化还可以将()省略:
1 | Thread{ |
同样还有最常用的点击事件接口OnClickListener
,也符合函数式API的形式:
1 | botton.setOnClickListener(new View.OnClickListener() { |
Kotlin中则可以简化成:
1 | button.setOnClickListener { |
就可以精简很多代码了。
let,with,apply
这三个函数均提供了函数API编程接口,即能接受lambda表达式
let
1 | obj.let {obj2 -> |
在上述代码中会自动将obj
参数传给obj2
,为了防止重名才取不同的名字
并且当只有一个参数时,可以用it代替。如现在有一个study类,类中有readBooks(),doHomework()
两个方法,可以变成:
1 | fun doStudy(study: Study) { |
通常在判空时使用
with
with
函数接收两个参数,第一个参数是任意类型的对象,第二个参数是lambda表达式,在lambda表达式中会提供第一个参数的上下文,并用最后一行作为返回值。如现在一个水果列表,要依次吃水果:
1 | val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") |
用with
方法就可以改成:
1 | val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon") |
另外,还有个run
函数和这个类似,只不过run函数是在某个对象的基础上使用,同样接受lambda表达式,其他则是一样的,最后一行返回值:
1 | val result = obj.run { |
apply
apply函数也很类似,只不过他不会返回一个值,而是自动返回调用对象本身:
1 | val resullt = obj.apply { |
比如$\texttt{SharedPreference}$中就可以使用apply简洁的添加数据。