zoukankan      html  css  js  c++  java
  • Kotlin基础(四)Lambda编程

    Lambda编程

    一、Lambda表达式和成员引用

    一)Lambda表达式语法

    1  //注意与Java8中的区别
    2     val sum={ x:Int,y:Int -> x+y }
    3     println(sum(5,6))
    4     run { print(33) }
     1 data class Person(val name:String,val age:Int)
     2 
     3 fun main(args: Array<String>) {
     4     val persons= listOf<Person>(Person("Tom",3),Person("Jerry",2))
     5     //println(persons.maxBy { it.age })
     6 
     7     //不使用任何简明语法的重写
     8     //println(persons.maxBy({p:Person -> p.age}))
     9 
    10     //如果lambda表达式是函数调用的最后一个实参,可以把它放到括号外面,但只能放一个
    11     //println(persons.maxBy() { p:Person -> p.age })
    12     
    13     //lambda为唯一实参时,可以省略小括号
    14     //println(persons.maxBy { p:Person -> p.age })
    15     
    16     //如果lambda的参数类型可以被推断出来,可以省略它
    17     //println(persons.maxBy { p -> p.age })
    18     //使用原则:可以先不声明参数类型,观察编译器是否报错
    19     
    20     //最简形式:使用默认参数名it代替参数名。如果当前上下文期望的
    21     //是只有一个参数的的lambda且这个参数的类型可以推断出来。
    22     println(persons.maxBy { it.age })
    23 }
     1 fun main(args: Array<String>) {
     2     //与Java不同,Kotlin允许在lambda内部访问非final变量,甚至修改它们
     3     //默认情况下,局部变量的声明周期被限制在声明这个变量的函数中。但是如果
     4     //它被lambda捕捉了,使用这个变量的代码可以被存储并稍后再执行。
     5     
     6     fun tryToCountButtonClicks(button:Button):Int{
     7         var count=0
     8         button.onClick {count++}
     9         //这里会始终返回0
    10         return count
    11     }
    12 }

    成员引用:

    //与Java8一样,如果把函数转换为一个值,你就可以传递它
        var getAge=Person :: age
    
        //还可以引用顶层函数
        run { ::tang }
    
        //构造方法引用存储或延期执行创建实例类的动作
        val createPerson= ::Person
        val p=createPerson("Price",48)
        println(p)
    
        //引用扩展函数
        fun Person.isAdult()= age>=21
        val isAdult=Person::isAdult

    二)集合的函数式API

    1.filter函数:遍历集合并选出应用给定lambda后返回true的那些元素。 

    1 val list=listOf(1,2,3,4,5,6)
    2 println(list.filter{it%2==0})
    3 /*[2, 4, 6]*/

    2.map函数:对集合中的每一个运用给定函数并把结果收集到一个新集合。

    val list= listOf(1,2,3)
    println(list.map{it
    *it})

    3.all函数:判断是否所有函数满足判定式

    1 val list= listOf(1,2,3,4,5,6,7)
    2 println(list.all{it>3})//false

    4.any函数:检查是否至少存在一个匹配的元素

    1 val list= listOf(1,2,3,4,5,6,7)
    2 println(list.any { it>3 })//true

    5.find函数:找到第一满足判定式的元素

    1 val list= listOf(1,2,3,4,5,6,7)
    2 println(list.find { it>3 })//4

    6.groupBy函数:把列表转换为分组的map

    1     val persons= listOf<Person>(Person("Tom",22), Person("Jimmy",22)
    2     , Person("Jack",33),Person("Blank",33), Person("Price",50))
    3     println(persons.groupBy { it.age })
    4     /*{22=[Person(name=Tom, age=22), Person(name=Jimmy, age=22)],
    5     33=[Person(name=Jack, age=33), Person(name=Blank, age=33)],
    6     50=[Person(name=Price, age=50)]}*/

    7.flatMap函数:处理嵌套集合中的元素

    1 val list= listOf<String>("abc","de","fchi")
    2 println(list)//[abc, de, fchi]
    3 println(list.flatMap { it.toList() })
    4  /*[a, b, c, d, e, f, c, h, i]*/

    8.flatten函数:只是平铺不做任何变换

    9.惰性操作集合:序列

     1 fun main(args: Array<String>) {
     2     val persons= listOf<Person>(Person("Ajax",2), Person("Bob",6),
     3             Person("Tom",5), Person("Auth",3))
     4     persons.map(Person::name).filter { it.startsWith("A") }
     5     persons.map { p:Person ->p.name }.filter { it.startsWith("A") }
     6     /*
     7     * 上面的代码存在的问题:链式调用会创建两个列表,导致效率低下
     8     * 此时可以使用序列
     9     * */
    10 
    11     persons.asSequence()         //把初始集合转换成序列
    12             .map(Person::name)   //序列支持和集合相同的API
    13             .filter { it.startsWith("A") }
    14             .toList()            //转换回集合
    15 
    16     /*
    17     * 序列操作分为两类:中间和末端。中间操作返回的是另一个序列,
    18     * 末端操作返回的是一个结果,这个结果可能是集合、元素、数字,
    19     * 或者其他从初始集合变换序列中获取的任意对象。
    20     * */
    21     //中间操作始终是惰性的
    22     listOf(1,2,3,4).asSequence()
    23             .map { println("map($it)"); it*it }    //没有末端操作不会被执行
    24             .filter { println("filter($it)") ; it%2==0}  //没有末端操作不会被执行
    25 }

    注意:序列与Java8的Steam的区别:序列不支持在多个CPU上并行执行。

    三)使用Java函数式接口

    1 /*Java*/
    2 void post(int delay,Runnable com){}
    TestIt().post(1000){ //注意整个程序只会创建一个Runnable实例
         println("Run it")
    }
    1 fun handle(id : String){      //lambda会捕捉id这个变量
    2     TestIt().post(1000){ println("Run it $id")} //所以每次调用都会创建新的实例
    3 }

    SAM构造方法:显示地lambda转换为函数式接口

    1 fun createAllDoneRunnable() :Runnable{
    2     //SAM构造方法名称和函数式接口名称一样,且只接收一个参数
    3     return Runnable { println("All done") }
    4 }
    5 
    6 //SAM构造方法还可以把从lambda生成的函数接口实例,存储在变量中
    7 val runIt= Runnable { println("Rock & Roll") }

    四)带接收者的lambda:with与apply

    1.with函数

     1 fun alphabet() :String{
     2     val result=StringBuilder()
     3     for (letter in 'A'..'Z'){
     4         result.append(letter)
     5     }
     6     result.append("
    Done")
     7     return result.toString()
     8 }
     9 
    10 //用with函数简化
    11 fun alphabe2() : String{
    12     val result=StringBuilder()
    13     //with结构实际上是一个接收两个参数的函数,一个参数
    14     //是result另一个是lambda表达式
    15     return with(result){
    16         for (letter in 'A'..'Z'){
    17             this.append(letter)
    18         }
    19         //可省略this
    20         append("
     Done2")
    21         toString()
    22     }
    23 }
    24 
    25 //进一步简化
    26 fun alphabet3()= with(StringBuilder()){
    27     for (letter in 'A'..'Z'){
    28         append(letter)
    29     }
    30     append("
     Done3")
    31     toString()
    32 }

    2.apply函数

    几乎与with函数一样,与with函数的唯一区别是会返回作为实参传递给它的对象(接收者对象)

    Simple is important!
  • 相关阅读:
    tomcat7项目启动报错java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory
    Android APP 分享图片文字到微信刚開始正常,后面就不弹出分享框了
    Akka 编程: 什么是Actor
    【3C认证】安防产品3C认证
    设计模式之装饰模式
    关于那些常见的坑爹的小bug(会持续更新)
    【Mac双系统设置系统默认启动系统】解决方式
    JEECG常见问题大全征集
    关于最新的Vuforia-unity3d-samples2-8-13
    python-print
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/8049671.html
Copyright © 2011-2022 走看看