美文网首页
Kotlin之lambda表达式

Kotlin之lambda表达式

作者: 有没有口罩给我一个 | 来源:发表于2018-05-28 20:06 被阅读0次

    lambda表达式也称λ 表达式,本质上就是可以传递给其他函数的一小段代码。

    class Button() {
        fun setOnClickListener(onClickListener: (OnClickListener) -> Unit) {
          }
    }
    
    val button = Button()
    button.setOnClickListener {
             .........事件触发回调
    }
    

    上述Button中setOnClickListener方法接收一个 (OnClickListener) -> Unit
    lambda表达式,即:函数的参数是一个lambda表达式类型,这就是Kotlin,当然阔以使用匿名内部类:

    view.onClickListener = object :  OnClickListener {
        override fun onClick(view: View) {
        }
    }
    

    这不是本节的内容,开始放大招了:结合Lambda+集合,最常用就是使用Lambda操作集合:

    //构造几个Person
    data class Person(val name: String, val age: Int)
    val persons: ArrayList<Person> = ArrayList()
    for (count in 0..10) {
        persons.add(Person("name$count", count + 2))
    }
    
    persons.filter { it -> it.age % 3 == 0 }.map(Persion::name).forEach(::println)
    

    看看这段代码,filter:就是过滤不满足it.age % 3 == 0 条件的元素,返回List<Person>,map:变换,最后返回List<String>;
    看一些filter方法的源码:

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

    看函数的参数:predicate: (T) -> Boolean,Lambda表达式,解析一下,T:泛型,从Iterable<T> ,在这个例子T就是就是Person ,返回值是Boolean,就是例子中的it.age % 3 == 0的结果,这些只是Lambda表达式的返回值,函数返回是一个列表List<T>,集合的变换中间会产生一个新的集合,在上几个操作集合常用的栗子?

    //过滤
    persons.filter { it -> it.age % 3 == 0 }.map(Persion::name).forEach(::println)
    //List<Person>  -> List<String> -> println
    persons.map(Persion::name).forEach(::println)
    //List<Person> -> maxPerson - println
    persons.maxBy(Persion::age).run(::println)
    //List<Person> -> sumAge -> println
    persons.sumBy(Persion::age).let(::println)
    
     println(persons.all { it.age > 10 })//匹配所有
    println(persons.any { it.age > 12 })//至少匹配一个
    println(persons.count { it.age > 12 })//满足该条件的元素个数
    println(persons.firstOrNull { it.age > 10 }?.name)//返回第一个或者返回null
    
    
    println(persons.groupBy { it.age })//按年龄分组 ,返回一个map:key = it.age,value=Person
    
    
    val books = ArrayList<Book>()
    for (index in 0..10) {
        books.add(Book("book$index", listOf("author$index", "author2$index")))
    }
    
    books.flatMap { it.authors }.toList().forEach(::println)
    
    val strings = listOf("abc", "def")
    println(strings.flatMap { it.toList() })//
    

    我刚刚在上面提了一下,这些操作中间会产生临时列表:

     persons.filter { it -> it.age % 3 == 0 }.map(Persion::name)
    

    filter和map都会返回一个列表,即:上面的链式调用会创建两个列表,数据少还好,要是百万级的,那就jj,怕不怕?反正我是怕了,有没有解决方案呢?答案是肯定滴,该序列上场了。

     //序列
    persons.asSequence().map(Persion::name).filter { it.startsWith("A") }.toList()
    

    Sequence 好像是Kotlin中惰性集合的入口,序列不需要创建中间列表来保存中间产生的数据。

    Sequence 是什么?

    就是一个可以逐个列举元素的元素序列

    执行序列操作:中间和末端操作

    序列操作分为两类:中间和末端操作,一次中间操作返回的是另一个序列,一次末端操作返回的是一个结果:

       persons.asSequence().map(Persion::name).filter { it.startsWith("A") }.toList()
    

    map和filter是中间的操作,toList()为末端操作,中间操作始终都是惰性的

    persons.asSequence().map(Persion::name).filter { 
        println(it)
      it.startsWith("A")
    }
    

    println(it)始终不会被执行(末端操作没有被调用;

    persons.asSequence().map(Persion::name).filter { 
        println(it)
      it.startsWith("A")
    }.toList()
    

    Sequence 和 列表的区别:列表会先把原始的列表变换成另一个列表,然后在从新列表中find,而Sequence 所有的操作是按顺序应用在每一个元素张,处理完第一个元素(先map在find),然后完成接着第二个元素的处理,find方法是返回的是第一个匹配元素。

    val listOf = listOf(1, 2, 3, 4)
    val map = listOf.map {
        println(it)
        it + 5
    }.find {
        println(it)
        it > 3
    }
    
    listOf.asSequence().map {
        println(it)
        it + 5
    }.find {
        println(it)
        it > 3
    }
    第一段结果是:1   2  3  4  6
    第二段结果:1   6
    

    很明显Sequence find的次数少于列表,性能优于列表,记住了老铁。

    如何创建Sequence?

    前面的栗子都是使用同一个方法创建Sequence :在集合上调用asSequence(),现在来说一下generateSequence函数。

    val takeWhile = generateSequence(0) {
        println(it)
        it + 1
    }.takeWhile { it <= 100 }
    println(takeWhile.sum())
    
     File("hello.txt").isHideden().let(::println)
    fun File.isHideden() = generateSequence(this) {
              it.parentFile
        }.any {
              it.isFile
    }
    

    Kotlin提供其他Lambda表达式相关的库函数
    学习Kotlin看官方文档很权威

    相关文章

      网友评论

          本文标题:Kotlin之lambda表达式

          本文链接:https://www.haomeiwen.com/subject/dsogjftx.html