日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Android進階之Kotlin高階函數(shù)和Lambda表達式詳細講解

前言

lambda語法在Java中已經(jīng)被廣泛的運用,我們在開發(fā)Android中幾乎上每一個項目也會在項目中接入Lambda插件,因為Lambda確實能簡少很多的代碼量。

目前創(chuàng)新互聯(lián)建站已為1000多家的企業(yè)提供了網(wǎng)站建設、域名、網(wǎng)絡空間、網(wǎng)站運營、企業(yè)網(wǎng)站設計、七星關區(qū)網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

無獨有偶,在Kotlin中也是Lambda語法的,在這篇文章中就詳細的為大家講解Lambda語法的編寫與使用

一、kotin高階函數(shù)詳解

1、高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)。這種函數(shù)的一個很好的例子是 lock(),它接受一個鎖對象和一個函數(shù),獲取鎖,運行函數(shù)并釋放鎖:

 
 
 
 
  1. fun  lock(lock: Lock, body: () -> T): T {
  2.     lock.lock()
  3.     try {
  4.         return body()
  5.     }
  6.     finally {
  7.         lock.unlock()
  8.     }
  9. }

body 擁有函數(shù)類型:() -> T,所以它應該是一個不帶參數(shù)并且返回 T 類型值的函數(shù)。它在 try{: .keyword }-代碼塊內(nèi)部調(diào)用、被 lock 保護,其結果由lock()函數(shù)返回。如果我們想調(diào)用lock()函數(shù),我們可以把另一個函數(shù)傳給它作為參數(shù)(參見函數(shù)引用)

2、如果一個函數(shù)接收另一個函數(shù)作為參數(shù),或者返回值的類型是另一個函數(shù),那么該函數(shù)就稱為高階函數(shù)

函數(shù)類型,基本規(guī)則如下:

(String,Int) -> Unit

現(xiàn)在將上述函數(shù)類型添加到某個函數(shù)的參數(shù)聲明或者返回值聲明上,那么這個函數(shù)就是一個高階函數(shù)了,例如

fun example(func: (String, Int) -> Unit) {

func("hello", 123)

}

可以看到這里的 example() 函數(shù)接收到了一個函數(shù)類型參數(shù),因此 example() 函數(shù)就是一個高階函數(shù);

這里我準備定義一個叫作 num1AndNum2() 的高階函數(shù),讓它接收兩個整形和一個函數(shù)類型的參數(shù)。我們會在 num1AndNum2() 函數(shù)中對傳入的兩個整型參數(shù)進行某種運算,并返回運行結果。但具體進行什么運算是由傳入的函數(shù)類型參數(shù)決定的

新建一個名為 Test1.kt 文件

 
 
 
 
  1. fun num1AndNum2(num1:Int,num2:Int,operation:(Int,Int)->Int):Int{
  2.     val result = operation(num1,num2)
  3.     return result
  4. }
  5. fun plus(num1: Int, num2: Int): Int {
  6.     return num1 + num2
  7. }
  8. fun minus(num1: Int, num2: Int): Int {
  9.     return num1 - num2
  10. }
  11.  main() 函數(shù)
  12. fun main(){
  13.     val num1 = 100
  14.     val num2 = 80
  15.     val result1 = num1AndNum2(num1,num2, ::plus)
  16.     val result2 = num1AndNum2(num1,num2,::minus)
  17.     println("result1:"+result1)
  18.     println("result2:"+result2)
  19. }
  20. result1:180
  21. result1:20

::plus 和 ::minus 的寫法,這是一種函數(shù)引用方式的寫法,表示將 plus() 和 minus() 函數(shù)作為參數(shù)傳遞給 num1AndNum2() 函數(shù)

如果每次調(diào)用任何高階函數(shù)時都還得先定義一個與其函數(shù)類型參數(shù)相匹配的函數(shù),是不是太復雜了?沒錯,因此 Kotlin 還支持其他多種方式來調(diào)用高階函數(shù),比如 Lambda 表達式、匿名函數(shù)、成員引用等。其中 Lambda 表達式是最常見也是最普遍的高階函數(shù)調(diào)用方式,剛才的代碼使用 Lambda 表達式來實現(xiàn)(Lambda 表達式最后一行自動作為返回值),plus() 和 minus() 函數(shù)可以刪掉了

 
 
 
 
  1. fun main() {
  2.     val num1 = 100
  3.     val num2 = 80
  4.     val result1 = num1AndNum2(num1, num2) { n1, n2 ->
  5.         n1 + n2
  6.     }
  7.     val result2 = num1AndNum2(num1, num2) { n1, n2 ->
  8.         n1 - n2
  9.     }
  10.     println("result1:" + result1)
  11.     println("result2:" + result2)
  12. }
  13. fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
  14.     val result = operation(num1, num2)
  15.     return result
  16. }

3、閉包函數(shù)

閉包函數(shù) 一個函數(shù)的返回值是函數(shù),函數(shù)的內(nèi)部包含另一個函數(shù),可以是有參無參的匿名函數(shù)

 
 
 
 
  1. fun main(args: Array) {
  2.     val mm = aaa()
  3.     println(mm())
  4.     println(mm())
  5.     println(mm())
  6.     println(mm())
  7.     println(mm())
  8.     val  kk = bbb()
  9.     println(kk("shadow")) //shadow --- 1
  10.     println(kk("shadow")) //shadow --- 2
  11.     println(kk("shadow")) //shadow --- 3
  12.     println(kk("shadow")) //shadow --- 4
  13.     println(kk("shadow")) //shadow --- 5
  14. }
  15. //閉包函數(shù) 就是函數(shù)作為返回參數(shù)
  16. fun aaa(): () -> (Int) {
  17.     var current = 10
  18.     return fun(): Int {
  19.         return current++
  20.     }
  21. }
  22. fun bbb(): (String) -> (String) {
  23.     var current = 0;
  24.     return fun(str: String): String {
  25.         current++;
  26.         return "$str --- $current";
  27.     }
  28. }

4、kotin中高階函數(shù)案例

map 變換

 
 
 
 
  1. fun main(args: Array) {
  2.     val list = listOf(1, 2, 3, 4, 5, 6)
  3.     val newList = list.map {
  4.         //對集合中的數(shù)據(jù)進行操作,然后賦值給新的集合
  5.         (it * 2).toString()
  6.     }.forEach(::println) //2 4 6 8 10 12
  7.     val doubleList = list.map {
  8.         it.toDouble()
  9.     }.forEach(::print) //1.0 2.0 3.0 4.0 5.0 6.0
  10.     //函數(shù)作為參數(shù)的第二種方式調(diào)用 類名::方法名
  11.     val doubleList2 = list.map(Int::toDouble).forEach(::print) ////1.0 2.0 3.0 4.0 5.0 6.0
  12. }

flatMap 對集合的集合進行變換

 
 
 
 
  1. fun main(args: Array) {
  2.     val list = arrayOf(
  3.         1..5,
  4.         50..55
  5.     )
  6.     //把多個數(shù)組集合變成一個數(shù)組,并且對數(shù)據(jù)進行變換
  7.     val mergeList = list.flatMap { intRange -> //集合內(nèi)的集合 1..5 , 50..55
  8.         intRange.map { intElement -> //集合內(nèi)集合遍歷 1,2,3,4,5
  9.             "No.$intElement"
  10.         }
  11.     }
  12.     //No.1 , No.2 , No.3 , No.4 , No.5 , No.50 , No.51 , No.52 , No.53 , No.54 , No.55 ,
  13.     mergeList.forEach { print("$it , ") }
  14.     println()
  15.     //直接多個數(shù)組集合變換成一個結集合
  16.     val newList = list.flatMap {
  17.         it
  18.     }
  19.     //1 , 2 , 3 , 4 , 5 , 50 , 51 , 52 , 53 , 54 , 55 ,
  20.     newList.forEach { print("$it , ") }
  21. }

filter 篩選

 
 
 
 
  1. fun main(args: Array) {
  2.     val list = arrayOf(
  3.         1..5,
  4.         2..3
  5.     )
  6.     val newList = list.flatMap {
  7.         it
  8.     }
  9.     //篩選 集合中數(shù)據(jù) > 2的item
  10.     val filterList = newList.filter { it > 2 }
  11.     filterList.forEach(::print) //3453
  12.     //篩選 集合中下標是奇數(shù)item
  13.     val filterIndexList = newList.filterIndexed { index, i -> index % 2 == 0; }
  14.     filterIndexList.forEach { print(it) } //1 3 5 3
  15. }

forEach

 
 
 
 
  1. fun main(args: Array) {
  2.     var list = listOf(1, 2, 3, 4, 5, 6)
  3.     list.forEach(::println)
  4.     val newList = arrayListOf() --->1,2,3,4,5,6
  5.     list.forEach {
  6.         newList.add((it * 2).toString()) --->2,4,6,8,10,12
  7.     }
  8.     newList.forEach(::println)
  9. }

下面我們就來介紹Lambda

二、Lambda表達式詳解

1、Lambda表達式是什么?

  • Lambda表達式是JDK8推出一個重要的新特性,雖然看著很高大上,其實Lambda表達式的本質(zhì)只是一個”語法糖”,習慣了面向?qū)ο缶幊痰乃枷?,一開始看起來會有點不習慣這種語法形式,但如果你學過C#,你就會發(fā)現(xiàn)語法和C#中的“委托”很像;
  • 大家都知道,在Java中萬物皆對象,Java 一直都致力維護其對象至上的特征,函數(shù)對 Java 而言雖然重要,但在 Java 的世界里,函數(shù)無法獨立存在,只能依賴于對象來調(diào)用。在函數(shù)式編程語言中,函數(shù)是一等公民,它們可以獨立存在,你可以將其賦值給一個變量,或?qū)⑺麄儺斪鰠?shù)傳給其他函數(shù)。JavaScript 就是函數(shù)式編程語言最典型的代表;
  • 函數(shù)式語言提供了一種強大的功能——閉包,相比于傳統(tǒng)的編程方法有很多優(yōu)勢,閉包是一個可調(diào)用的對象,它記錄了一些信息,這些信息來自于創(chuàng)建它的作用域。因此Java 現(xiàn)在提供的最接近閉包的概念便是 Lambda 表達式,雖然閉包與 Lambda 表達式之間存在顯著差別,但至少 Lambda 表達式是閉包很好的替代者;
  • 使用Lambda表達式的目的就是取代大部分的匿名內(nèi)部類,讓我們能寫出更簡潔優(yōu)雅的 Java 代碼,尤其在集合的遍歷和其他集合操作中,可以極大地優(yōu)化代碼結構。JDK 也提供了大量的內(nèi)置函數(shù)式接口供我們使用,使得 Lambda 表達式的運用更加方便、高效;
  • 如果在你沒有熟練掌握Lambda表達式時,不建議亂用,因為不使用Lambda表達式,你同樣可以實現(xiàn)相應功能,只把它當做一種錦上添花的工具就可以了;

2、Lambda表達式語法結構

Lambda表達式基礎語法結構如下:

 
 
 
 
  1. (parameters) -> expression
  2. (parameters) ->{ statements; }

其中 () 用來描述參數(shù)列表,{} 用來描述方法體,-> 為 lambda運算符 ,讀作(goes to),parameters表示參數(shù),expression表示表達式,statements表示代碼塊。

結構說明如下:

一個 Lambda 表達式可以有零個或多個參數(shù)

參數(shù)的類型既可以明確聲明,也可以根據(jù)上下文來推斷。

例如:

(int a)與(a)效果相同

所有參數(shù)需包含在圓括號內(nèi),參數(shù)之間用逗號相隔。

例如:

 
 
 
 
  1. (a, b) 或 (int a, int b) 或 (String a, int b, float c)

空圓括號代表參數(shù)集為空。例如:() -> 42

當只有一個參數(shù),且其類型可推導時,圓括號()可省略。

例如:a -> return a*a

Lambda 表達式的主體可包含零條或多條語句

如果 Lambda 表達式的主體只有一條語句,花括號{}可省略。匿名函數(shù)的返回類型與該主體表達式一致;

如果 Lambda 表達式的主體包含一條以上語句,則表達式必須包含在花括號{}中(形成代碼塊)。匿名函數(shù)的返回類型與代碼塊的返回類型一致,若沒有返回則為空;

3、Lambda表達式重要特征

  • 可選類型聲明:不需要聲明參數(shù)類型,編譯器可以統(tǒng)一識別參數(shù)值。
  • 可選的參數(shù)圓括號:一個參數(shù)無需定義圓括號,但多個參數(shù)需要定義圓括號。
  • 可選的大括號:如果主體包含了一個語句,就不需要使用大括號。
  • 可選的返回關鍵字:如果主體只有一個表達式返回值則編譯器會自動返回值,大括號需要指定明表達式返回了一個數(shù)值。

4、函數(shù)式接口詳解

①什么是函數(shù)式接口

函數(shù)式接口在java中是指只有一個抽象方法的接口。

函數(shù)式接口,就是適用于函數(shù)式編程場景的接口。在java中函數(shù)式編程就體現(xiàn)在Lambda,因此函數(shù)式接口就是能夠適用于lambda使用的接口。只有確保接口中有且僅有一個抽象方法,lambda才能進行順利的推導;

②語法

@FunctionalInterface注解

注解和@override注解的作用類似。該住處應用于函數(shù)式接口的定義上。

一旦使用了該注解來定義函數(shù)式接口,編譯器就會檢查該接口是否是有且僅有一個抽象方法

 
 
 
 
  1. @FunctionalInterface
  2. public interface MyFunctionalInterface {
  3.       void myMethod();
  4. }
  5. 將函數(shù)式接口作為方法的參數(shù)
  6. public class Demo {
  7.     private static void dos(FunctionInterface fi){
  8.         fi.method();
  9.     }
  10.     public static void main(String[] args) {
  11.         Demo.dos(()->{System.out.println("lambda表達式");});
  12.     }

5、Lambda表達式基本使用案例

表達式基本使用案例

 
 
 
 
  1. // 1. 不需要參數(shù),返回值為 5  
  2. () -> 5  
  3. // 2. 接收一個參數(shù)(數(shù)字類型),返回其2倍的值  
  4. x -> 2 * x  
  5. // 3. 接受2個參數(shù)(數(shù)字),并返回他們的差值  
  6. (x, y) -> x – y  
  7. // 4. 接收2個int型整數(shù),返回他們的和  
  8. (int x, int y) -> x + y  
  9. // 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void)  
  10. (String s) -> System.out.print(s)
  11. 定義6個接口,后面我們都會基于這6個接口來演示案例
  12. /**多參數(shù)無返回*/
 
 
 
 
  1. @FunctionalInterface
  2. public interface NoReturnMultiParam {
  3.     void method(int a, int b);
  4. }
  5. /**無參無返回值*/
  6. @FunctionalInterface
  7. public interface NoReturnNoParam {
  8.     void method();
  9. }
  10. /**一個參數(shù)無返回*/
  11. @FunctionalInterface
  12. public interface NoReturnOneParam {
  13.     void method(int a);
  14. }
  15. /**多個參數(shù)有返回值*/
  16. @FunctionalInterface
  17. public interface ReturnMultiParam {
  18.     int method(int a, int b);
  19. }
  20. /** 無參有返回*/
  21. @FunctionalInterface
  22. public interface ReturnNoParam {
  23.     int method();
  24. }
  25. /**一個參數(shù)有返回值*/
  26. @FunctionalInterface
  27. public interface ReturnOneParam {
  28.     int method(int a);
  29. }
  30. 案例代碼:
  31. public class Test2 {
  32.     public static void main(String[] args) {
  33.         //1.簡化參數(shù)類型,可以不寫參數(shù)類型,但是必須所有參數(shù)都不寫
  34.         NoReturnMultiParam lamdba1 = (a, b) -> {
  35.             System.out.println("簡化參數(shù)類型");
  36.         };
  37.         lamdba1.method(1, 2);
  38.         //2.簡化參數(shù)小括號,如果只有一個參數(shù)則可以省略參數(shù)小括號
  39.         NoReturnOneParam lambda2 = a -> {
  40.             System.out.println("簡化參數(shù)小括號");
  41.         };
  42.         lambda2.method(1);
  43.         //3.簡化方法體大括號,如果方法條只有一條語句,則可以省略方法體大括號,類似if或for
  44.         NoReturnNoParam lambda3 = () -> System.out.println("簡化方法體大括號");
  45.         lambda3.method();
  46.         //4.如果方法體只有一條語句,并且是 return 語句,則可以省略方法體大括號
  47.         ReturnOneParam lambda4 = a -> a+3;
  48.         System.out.println(lambda4.method(5));
  49.         ReturnMultiParam lambda5 = (a, b) -> a+b;
  50.         System.out.println(lambda5.method(1, 1));
  51.     }
  52. }

6、使用lambda 表達式去引用方法

①引用方法的語法為:方法歸屬者::方法名

注意:靜態(tài)方法的歸屬者為類名,普通方法歸屬者為對象。該代碼案例結合最上面的自定義函數(shù)式接口:

 
 
 
 
  1. public class Exe1 {
  2.     public static void main(String[] args) {
  3.         ReturnOneParam lambda1 = a -> doubleNum(a);
  4.         System.out.println(lambda1.method(3));
  5.         //lambda2 引用了已經(jīng)實現(xiàn)的 doubleNum 方法
  6.         ReturnOneParam lambda2 = Exe1::doubleNum;
  7.         System.out.println(lambda2.method(3));
  8.         Exe1 exe = new Exe1();
  9.         //lambda4 引用了已經(jīng)實現(xiàn)的 addTwo 方法
  10.         ReturnOneParam lambda4 = exe::addTwo;
  11.         System.out.println(lambda4.method(2));
  12.     }
  13.     /**
  14.      * 要求
  15.      * 1.參數(shù)數(shù)量和類型要與接口中定義的一致
  16.      * 2.返回值類型要與接口中定義的一致
  17.      */
  18.     public static int doubleNum(int a) {
  19.         return a * 2;
  20.     }
  21.     public int addTwo(int a) {
  22.         return a + 2;
  23.     }
  24. }

②構造方法的引用

一般我們需要聲明接口,該接口作為對象的生成器,通過 類名::new 的方式來實例化對象,然后調(diào)用方法返回對象。

 
 
 
 
  1. interface ItemCreatorBlankConstruct {
  2.     Item getItem();
  3. }
  4. interface ItemCreatorParamContruct {
  5.     Item getItem(int id, String name, double price);
  6. }
  7. public class Exe2 {
  8.     public static void main(String[] args) {
  9.         ItemCreatorBlankConstruct creator = () -> new Item();
  10.         Item item = creator.getItem();
  11.         ItemCreatorBlankConstruct creator2 = Item::new;
  12.         Item item2 = creator2.getItem();
  13.         ItemCreatorParamContruct creator3 = Item::new;
  14.         Item item3 = creator3.getItem(119, "電腦", 5888.88);
  15.     }
  16. }

使用匿名類與 Lambda 表達式的一大區(qū)別在于關鍵詞的使用。

對于匿名類,關鍵詞 this 解讀為匿名類,而對于 Lambda 表達式,關鍵詞 this 解讀為寫就 Lambda 的外部類

7、Lambda再次總結

  • 無參、無返回值的函數(shù)類型(Unit 返回類型不可省略):() -> Unit;
  • 接收T類型參數(shù)、無返回值的函數(shù)類型:(T) -> Unit;
  • 接收T類型和A類型參數(shù)、無返回值的函數(shù)類型(多個參數(shù)同理):(T,A) -> Unit;
  • 接收T類型參數(shù),并且返回R類型值的函數(shù)類型:(T) -> R;
  • 接收T類型和A類型參數(shù)、并且返回R類型值的函數(shù)類型(多個參數(shù)同理):(T,A) -> R;
  • 在大括號{}的方法實現(xiàn)里,如果只有一個參數(shù),可以用it指定而不需要再寫x->...這種代碼;
  • 如果方法實現(xiàn)里有多個參數(shù),則需要x:Int,y:Int->...這種方式指明->后面的自定義參數(shù)名;

總結

1、Lambda和高階函數(shù)理解起來有點繞,需要大量的練習和實驗才能慢慢的理解

2、Lambda很深,我們一起來學習進步


分享題目:Android進階之Kotlin高階函數(shù)和Lambda表達式詳細講解
文章起源:http://www.dlmjj.cn/article/dhgicch.html