文章目录


函数式编程

【Kotlin】高阶函数_高阶函数
【Kotlin】高阶函数_函数式编程_02
【Kotlin】高阶函数_测试类_03

举个栗子:forEach

var print = fun (name:String):Unit{
println(name)
}

fun main(args: Array<String>) {
var names = listOf<String>("Tom,Jerry,Lucy")
//forEach接收的参数为一个函数
names.forEach(print)
}

运行结果
【Kotlin】高阶函数_函数式编程_04
forEach接收的参数为一个函数,这个函数叫action,这个函数的作用就是:在集合里遍历,对于每个element都执行这个函数
【Kotlin】高阶函数_函数式编程_05
所以上边的代码等价于

for(element in names){
println(element)
}

forEach就是一个高阶函数,高阶函数就是参数或返回值是函数的函数

刚才的写法是比较麻烦的,简化如下:

var names = listOf<String>("Tom,Jerry,Lucy")
names.forEach{
a -> println(a)
}

forEach后边跟一个大括号,里边是一个匿名函数,参数是a,函数的内容是println(a)

还可以进一步简化,参数默认是it

var names = listOf<String>("Tom,Jerry,Lucy")
names.forEach{
println(it)
}

这样的一段代码,就叫闭包

一段程序代码通常由常量、变量和表达式组成,然后使用一对花括号“{}”来表示闭合,并包裹着这些代码,由这对花括号包裹着的代码块就是一个闭包

传统写法的缺点

现在有一个类Girl,里边存储了同宿舍女生的信息

data class Girl(var name:String,var age:Int,var height:Int,var address:String)
var girls = listOf<Girl>(
Girl("琼琼",27,163,"沧州"),
Girl("嫚嫚",29,160,"廊坊"),
Girl("二帆",30,160,"廊坊"),
Girl("真真",28,168,"福建"),
Girl("富婆",30,158,"贵州")
)

传送门:​【Kotlin】data class​

现在筛选出廊坊的舍友,写一个测试类HelloWorld

fun main(args: Array<String>) {
var langfangGirl = ArrayList<Girl>()
for(girl in girls){
if(girl.address == "廊坊"){
langfangGirl.add(girl)
}
}
for(girl in langfangGirl){
println("${girl.address} ${girl.age} 的 ${girl.name}")
}
}

【Kotlin】高阶函数_DSL_06
当然可以在Girl.kt中写一个方法

......
fun filterByAddress(address:String){
var addressGirls = ArrayList<Girl>()
for(girl in girls){
if(girl.address == address){
addressGirls.add(girl)
}
}
for(girl in addressGirls){
println("${girl.address} ${girl.age} 的 ${girl.name}")
}
}

测试类中可以直接调用了

fun main(args: Array<String>) {
filterByAddress("贵州")
}

【Kotlin】高阶函数_测试类_07
现在要通过年龄筛选,所以再增加一个按年龄筛选的方法,筛选出小于某一年龄的舍友

fun filterByAge(age:Int){
var ageGirls = ArrayList<Girl>()
for(girl in girls){
if(girl.age < age){
ageGirls.add(girl)
}
}
for(girl in ageGirls){
println("${girl.address} ${girl.age} 的 ${girl.name}")
}
}

现在又要通过地址和年龄两个筛选条件筛选,所以再增加一个方法

fun filterByAddressAge(address:String,age:Int){
var addressAgeGirls = ArrayList<Girl>()
for(girl in girls){
if((girl.address == address) and (girl.age < age)){
addressAgeGirls.add(girl)
}
}
for(girl in addressAgeGirls){
println("${girl.address} ${girl.age} 的 ${girl.name}")
}
}

通过上边的需求的不断变化,可以发现,几个需求的实现方法基本是复制粘贴,那么怎样让代码更简洁呢,需要了解以下知识了

高阶函数

maxBy、minBy

【Kotlin】高阶函数_kotlin_08
【Kotlin】高阶函数_测试类_09
现在有个需求,找到宿舍中最年长的舍友,如果按照java程序员的思路是这样写的

var maxAge = 0
for(girl in girls){
if(girl.age > maxAge){
maxAge = girl.age
}
}

println("年龄最大的值是${maxAge}")

for(girl in girls){
if(girl.age == maxAge){
println(girl)
}
}

【Kotlin】高阶函数_kotlin_10
如果是Kotlin程序员,这个需求对于他们来说就太简单了

println(girls.maxBy{it.age})

maxBy方法返回第一个满足指定评判标准的最大值
【Kotlin】高阶函数_测试类_11
也可以找到年龄最低的舍友

println(girls.minBy{it.age})

【Kotlin】高阶函数_kotlin_12

filter

现在筛选年龄<29,身高>165的舍友

println(girls.filter{
(it.age<29) and (it.height > 160)
})

【Kotlin】高阶函数_kotlin_13

map

【Kotlin】高阶函数_高阶函数_14

println(girls.map{
"${it.name}:${it.age}"
})

【Kotlin】高阶函数_函数式编程_15

any

判断有没有29岁的舍友

println(girls.any{
it.age == 29
})

【Kotlin】高阶函数_kotlin_16

count

查找年龄<29岁的舍友的数量

println(girls.count{
it.age < 29
})

【Kotlin】高阶函数_测试类_17

find

找到第一个符合条件的舍友并返回,例如查找地址为福建的舍友

println(girls.find{
it.address == "福建"
})

【Kotlin】高阶函数_高阶函数_18

groupBy

【Kotlin】高阶函数_高阶函数_19
按照地区进行分组

println(girls.groupBy{
it.address
})

查看运行结果

{沧州=[Girl(name=琼琼, age=27, height=163, address=沧州)], 
廊坊=[Girl(name=嫚嫚, age=29, height=160, address=廊坊), Girl(name=二帆, age=30, height=160, address=廊坊)],
福建=[Girl(name=真真, age=28, height=168, address=福建)],
贵州=[Girl(name=富婆, age=30, height=158, address=贵州)]}

查找地区为廊坊的小伙伴,并打印,注意​​?​​,不为空打印

girls.groupBy{
it.address
}.get("廊坊")?.forEach{
println(it)
}

【Kotlin】高阶函数_kotlin_20

DSL

【Kotlin】高阶函数_kotlin_21

扩展函数

在Girls.kt中增加一个方法

fun List<Girl>.findAge(age:Int){
filter{
it.age < age
}.forEach{
println(it)
}
}

测试下

fun main(args: Array<String>) {
girls.findAge(28)
}

【Kotlin】高阶函数_测试类_22
我们可以用关键字​​​infix​​修改方法

infix fun List<Girl>.findAge(age:Int){
filter{
it.age < age
}.forEach{
println(it)
}
}

调用的时候就可以直接空格调用了

girls findAge 28

运行结果是一样的