Kotlin基礎(四)Lambda編程
阿新 • • 發佈:2017-12-18
構造 引用 元素 允許 其他 create text 顯示 tag
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("\nDone") 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("\n Done2") 21 toString() 22 } 23 } 24 25 //進一步簡化 26 fun alphabet3()= with(StringBuilder()){ 27 for (letter in ‘A‘..‘Z‘){ 28 append(letter) 29 } 30 append("\n Done3") 31 toString() 32 }
2.apply函數
幾乎與with函數一樣,與with函數的唯一區別是會返回作為實參傳遞給它的對象(接收者對象)
Kotlin基礎(四)Lambda編程