Kotlin高阶函数(上)

  • maxby/minby
  • filter
  • map
  • any

高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
在Kotlin中,也有一些高阶函数,能够帮助我们简化代码,降低实现功能所需的代码量。接下来我将列出几个常见的高阶函数并对源码进行分析,以方便记忆和理解。

maxby/minby

顾名思义,maxby和minby就是求得最大值和最小值的方法。通常,在Java中我们是这样求得最大值与最小值的(普通方法)
假定数据库dogdatabase,内部存有数据:

data class dog(var name:String,var kind:String,var hight:Int,var address:String)
var dogdatabase= listOf<dog>(
        dog("妞妞","萨摩耶",23,"北京"),dog("阿贵","田园犬",22,"伊拉克"),
        dog("二哈","哈士奇",21,"上海"),dog("撒狗","田园犬",6,"新疆"),
        dog("小Q","柴犬",15,"北京"),dog("卤蛋","贵宾犬",21,"新疆"),
        dog("妞妞1","不丹",14,"广州"),dog("卤鸡","藏獒",32,"河北"),
        dog("妞妞2","萨摩耶",26,"广州"),dog("冒菜","拉布拉多",44,"河北"),
        dog("老麻","哈士奇",28,"哈尔滨"),dog("阿花","拉布拉多",44,"北京")
    )

求得身高最高的狗狗

fun main(args:Array<String>){
	var maxheight=0
	for(i in dogdatabase)
	{	
		if(i.height>maxheight)
		{	
			maxheight=i.height
		}
	}
	for(i in dogdatabase)
	{
		if(i.height=maxheight)
		{
			println("身高最高的狗狗是${i.name},身高是${i.height}")
		}
	}
}

通常,这在实现某些功能的时候成为了一个“固定格式”,在Kotlin中,创作者们将其实现为高阶函数maxby,我们只需要进行一下的操作:

fun main(args:Array<String>){                                                 
    //maxby 找最大数                                                     
    var maxhight=dogdatabase.maxBy{it.hight}                                                              
    println(maxhight)                                                
}

这样能够减少代码量,但是会出现一个问题,这个maxby只会输出一个最大值,如果我们有两个值同时满足最大,那么另外一个值将会被忽略。
以下是源码:

public inline fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? {
    val iterator = iterator()
    if (!iterator.hasNext()) return null
    var maxElem = iterator.next()
    if (!iterator.hasNext()) return maxElem
    var maxValue = selector(maxElem)
    do {
        val e = iterator.next()
        val v = selector(e)
        if (maxValue < v) {
            maxElem = e
            maxValue = v
        }
    } while (iterator.hasNext())
    return maxElem
}

在这里maxby的传入参数为selector,定义了一个iterator迭代器来对值进行筛选,如果hasnext为空,则传入的参数为Null,返回一个null,接下来定义了一个最大值,在传入有值得情况下,将分为数据个数为1的情况与大于1的情况。如果等于一则直接返回该值为最大值max,如果大于一,则在指针不指向空的情况下,指针依次后移对数据进行比较,如果较大则将该值得集合赋予maxElem,最后返回一个有最大值的maxElem集合。
minby的原理和maxby类似。

filter

filter是一个过滤器,能够通过各种条件过滤出符合该条件的数据。

println(dogdatabase.filter { it.address=="新疆" && it.kind=="田园犬" })     

可以得到结果:

[dog(name=撒狗, kind=田园犬, hight=6, address=新疆)]

源码如下:

public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}

它接受一个(T)->Boolean类型的函数,返回。但是它并不自己执行操作,而是新建一个ArrayList作为操作目标,然后把这个ArrayList和传入函数打包送给filterTo函数处理:
filterTo()函数会遍历数组内的元素,验证每个元素是否符合predicate函数,如果符合就把它添加到目标集合destination中,也就是说filter函数返回所有传入函数为true的元素。

map

map可以理解为映射,能够将符合要求的数据映射到一个数组中。
源码如下:

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

它接受一个(T) -> R类型的函数,返回。但是并不执行操作,而是将新建一个ArrayList作为操作目标,然后把这个ArrayList和传入函数打包送给mapTo函数处理:

public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
    for (item in this)
        destination.add(transform(item))
    return destination
}

mapto中将传入的arraylist中的item进行筛选,如果item在其中,则将其对应的transform加入destination,遍历后将结果destination以数组的方式返回。

所以我们可以这样使用它:

println(dogdatabase.map { "${it.name},${it.kind}"}) 

将狗狗数据库中的名字和种类映射并打印显示
得到结果:

[妞妞,萨摩耶, 阿贵,田园犬, 二哈,哈士奇, 撒狗,田园犬, 小Q,柴犬, 卤蛋,贵宾犬, 妞妞1,不丹, 卤鸡,藏獒, 妞妞2,萨摩耶, 冒菜,拉布拉多, 老麻,哈士奇, 阿花,拉布拉多]

any

any用来判断在数据中有没有符合条件的数据,返回的结果为布尔类型的值。true或者false
源码如下:

public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return false
    for (element in this) if (predicate(element)) return true
    return false
}

在这里,any接受一个(T) -> Boolean类型的函数,先进行判空操作,如果传入predicate为空则返回false,
如果不为空,则循环遍历element,匹配到对应数据则返回true,没有匹配到数据则返回false
在这里找一个狗狗数据库中是否有田园犬:

  println(dogdatabase.any{it.kind=="田园犬"}) 
  //得到结果
  true

在下一篇中,将继续对其他的高阶函数进行分析和记忆。

发布了15 篇原创文章 · 获赞 3 · 访问量 342

猜你喜欢

转载自blog.csdn.net/Py_csdn_/article/details/104765541