【Kotlin】高阶函数

函数式编程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

举个栗子: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)
}

运行结果
在这里插入图片描述
forEach接收的参数为一个函数,这个函数叫action,这个函数的作用就是:在集合里遍历,对于每个element都执行这个函数
在这里插入图片描述
所以上边的代码等价于

	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}")
	}
}

在这里插入图片描述
当然可以在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("贵州")
}

在这里插入图片描述
现在要通过年龄筛选,所以再增加一个按年龄筛选的方法,筛选出小于某一年龄的舍友

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

在这里插入图片描述
在这里插入图片描述
现在有个需求,找到宿舍中最年长的舍友,如果按照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程序员,这个需求对于他们来说就太简单了

println(girls.maxBy{it.age})

maxBy方法返回第一个满足指定评判标准的最大值
在这里插入图片描述
也可以找到年龄最低的舍友

println(girls.minBy{it.age})

在这里插入图片描述

filter

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

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

在这里插入图片描述

map

在这里插入图片描述

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

在这里插入图片描述

any

判断有没有29岁的舍友

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

在这里插入图片描述

count

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

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

在这里插入图片描述

find

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

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

groupBy

在这里插入图片描述
按照地区进行分组

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)
	}

在这里插入图片描述

DSL

在这里插入图片描述

扩展函数

在Girls.kt中增加一个方法

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

测试下

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

在这里插入图片描述
我们可以用关键字infix修改方法

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

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

girls findAge 28

运行结果是一样的

发布了640 篇原创文章 · 获赞 143 · 访问量 54万+

猜你喜欢

转载自blog.csdn.net/u010356768/article/details/103064780