Lambda01 编程范式、lambda表达式与匿名内部类、函数式接口、lambda表达式的写法...
?
1 編程范式
主要的編程范式有三種:命令式編程,聲明式編程和函數式編程。
1.1 命令式編程
關注計算機執行的步驟,就是告訴計算機先做什么后做什么
1.2 聲明式編程
表達程序的執行邏輯,就是告訴計算機要做什么,不指定具體怎么做
1.3 函數式編程
跟聲明式編程類似,就是告訴計算機做什么,不指定具體怎么做
參考博文
1.4 demo實例
1.4.1 需求
隨機產生一個int類型的數組,分別利用命令式編程和函數值編程獲取數組中的最小值
1.4.2 思路
命令式編程:
隨記產生int類型數組 -> 定義一個int類型變量minNumber并取int的最大值 -> 利用循環遍歷數組 -> 將數組中的每個元素和minNumber進行比較,如果比minNumber小就復制給minNumber,否則就進行下一次循環
函數值編程:
隨記產生int類型數組 -> 定義一個int類型的變量minNumber并取int的最大值 -> 將數組轉化成流 -> 調用的流的相關方法獲取流中的最小值 -> 將獲取到的最小值進行類型轉化后在復制給minNumber
1.4.3 代碼實現
package a_test_demo;import org.junit.Before; import org.junit.Test;import java.util.Arrays; import java.util.Random; import java.util.stream.IntStream;/*** @author 王楊帥* @create 2018-06-24 17:14* @desc**/ public class Case02 {/*** 需求:隨機產生一個int類型的數組并通過命令式編程和函數式編程分別求出數組中的最小值*/private int[] nums; // 定義一個int類型的數組int count = 10; // 數組長度Random random; // 隨機數對象 @Beforepublic void init() {random = new Random(); // 實例化Randomnums = new int[count]; // 實例化數組for (int i = 0; i < nums.length; i++) { // 修改數組內容nums[i] = random.nextInt(30);} // System.out.println(Arrays.toString(nums)); // 打印數組信息【測試用】 }/*** 利用命令式編程實現*/@Testpublic void test01() {int minNumber = Integer.MAX_VALUE; // 存儲最小值【初始化時時最大值】for (int i = 0; i < nums.length; i++) {if (minNumber > nums[i]) {minNumber = nums[i];}}System.out.println(Arrays.toString(nums) + " 中的最小值為: " + minNumber);}/*** 利用函數式編程實現*/@Testpublic void test02() {int minNumber = Integer.MAX_VALUE;minNumber = IntStream.of(nums) // 將數組轉化成流.parallel() // 設置并行處理【PS: 如果是命令式編程需要自己實現相應邏輯】.min() // 獲取流中的最小值.getAsInt(); // 將值轉化成int類型 System.out.println(Arrays.toString(nums) + " 中的最小值為: " + minNumber);}} View Code?
2 lambda表達式與匿名內部類
2.1 需求
現有一個名為getName的方法,該方法的參數是一個Student接口;怎么調用getName方法
2.2 思路
2.2.1 思路一
創建一個名為StudentImpl的類,該類實現了Student接口 -> 調用getName方法時傳入StudentImpl的實例即可
2.2.2 思路二
利用匿名內部類作為getName方法的實參
2.2.3 思路三
利用lambda表達式作為getName方法的實參
2.3 代碼實現
package a_test_demo;import org.junit.Test;public class Case01 {/*** getName方法:用戶打印學生的姓名* @param student Student接口*/public void getName(Student student) {System.out.println("學生的姓名為:" + student.name());}/*** 利用實現類實現*/@Testpublic void test01() {Student student = new StudentImpl();getName(student);}/*** 利用匿名內部類實現*/@Testpublic void test02() {getName(new Student() {@Overridepublic String name() {return "fury";}});}/*** 利用lambda表達式實現*/@Testpublic void test03() {getName(() -> "zeus");}}/*** Student接口*/ interface Student {/*** 抽象方法:返回String類型的姓名* @return*/String name(); }/*** Student接口的實現類*/ class StudentImpl implements Student {@Overridepublic String name() {return "warrior";} } View Code2.4 三種方法使用場景
2.4.1 實現類
當某個類需要實例化多次時使用
2.4.2 匿名內部類
某個類只需要實例化一次而且不需要知道實例名稱時使用【通常這個類需要進行重寫的方法不止一個】;如果需要知道實例名稱時就需要使用內部類
2.4.3 lambda表達式
某個類需要實例化一次而且不需要知道實例名字【這個類中通常有且只有一個需要重寫的方法】
2.5 為什么Lambda表達式可以作為方法的參數呢
Lambda 可以作為方法的參數。Lambda 表達式是函數式接口實現類的實例,所以,Lambda 表達式作為方法的參數,實際就是把一個類實例作為方法的參數。Lambda 表達式表達或是設計了一組功能,把它傳遞給方法作為參數,實際上,可以理解為把一組功能傳遞給了方法。因此,為了讓代碼更加簡潔,編程更加高效,調用方法(該方法的參數類型是接口類型)時,若接口有多個抽象方法,我們可以創建這個接口的匿名實現類的實例,作為方法的參數。若是接口只有唯一一個抽象方法,比如函數式接口,我們可以創建這個接口的 Lambda 表達式,作為調用方法的參數,把一組功能傳遞給方法。
技巧01:lambda表達式 “->” 左邊相當于函數式接口中那個方法的形參,“->” 的右邊相當于函數式接口中那個方法的返回值
??
技巧02:函數式接口就是只有一個抽象方法的接口
?
3 函數式接口
就是只有一個抽象函數的接口
3.1 默認實現的方法
如果一個函數式接口中有一個方法有default修飾,那么這個方法就叫做默認實現的方法【即:在接口中已經實現了方法相應的邏輯(從JDK1.8新增的特性)】,那么這個默認實現的方法不會算作是函數式接口的抽象方法,因為函數式接口的定義是:接口中只有一個抽象方法。
@FunctionalInterface interface IntFace {int doubuleNum(int i); // int test(); // 加了這個方法后,就會報錯/*** 默認實現的方法【即:接口中的方法已經實現了業務邏輯】* @param a* @param b* @return*/default int add(int a, int b) {return a + b;}}3.2 注解 @FunctionalInterface
該注解的作用是標名接口是函數式接口,并對該接口進行檢查,如果有超過一個抽象方法就會報錯
技巧01:如果某個接口中只有一個抽象方法,那么會被默認為是一個函數式接口,不用添加@FunctionalInterface注解也可以,@FunctionalInterface注解只是一個信息型注解而已
3.3 自定義函數式接口
3.3.1 需求
自定義一個函數式接口MoneyFormat,該接口中有一個接收int類型并且返回String類型的抽象方法format;MyMoney類中有一個printMoney方法的參數類型是MoneyFormat;創建MyMoney后如何調用printMoney方法
/*** 自定義函數式接口*/ @FunctionalInterface interface MoneyFormat {String format(int money); }/*** 自定義類*/ class MyMoney {private int money;/*** 有參構造器* @param money*/public MyMoney(int money) {this.money = money;}/**** @param moneyFormat 自定義函數式接口類型*/public void printMoney(MoneyFormat moneyFormat) {System.out.println("我的存款為:" + moneyFormat.format(this.money));} } View Code3.3.2 思路
實現類實現:太low,很麻煩,需要創建一個MoneyFormat的實現類
匿名內部類實現:還行,但是不美觀
lambda:簡單、粗暴、有成效
package a_test_demo;import org.junit.Test;import java.text.DecimalFormat;/*** @author 王楊帥* @create 2018-06-24 22:04* @desc**/ public class Case03 {/*** 實現類實現*/@Testpublic void test01() {MyMoney myMoney = new MyMoney(99912333);MoneyFormatImpl moneyFormat = new MoneyFormatImpl();myMoney.printMoney(moneyFormat);}/*** 利用匿名內部內實現*/@Testpublic void test02() {MyMoney myMoney = new MyMoney(9999999);myMoney.printMoney(new MoneyFormat() {@Overridepublic String format(int money) {return new DecimalFormat("#,###").format(money);}});}/*** lambda表達式實現*/@Testpublic void test03() {MyMoney myMoney = new MyMoney(999888888);myMoney.printMoney(money -> new DecimalFormat("#,###").format(money));}}/*** 自定義函數式接口*/ @FunctionalInterface interface MoneyFormat {String format(int money); }/*** 自定義類*/ class MyMoney {private int money;/*** 有參構造器* @param money*/public MyMoney(int money) {this.money = money;}/**** @param moneyFormat 自定義函數式接口類型*/public void printMoney(MoneyFormat moneyFormat) {System.out.println("我的存款為:" + moneyFormat.format(this.money));} }class MoneyFormatImpl implements MoneyFormat {@Overridepublic String format(int money) {return new DecimalFormat("#,##").format(money);} } View Code3.3.3 改進
JDK1.8開始提供了多個可供選擇的函數是接口,所以我們可以不用自己定義啦,選擇一個合適的拿過來用就可以啦
package a_test_demo;import org.junit.Test;import java.text.DecimalFormat; import java.util.function.Function;/*** @author 王楊帥* @create 2018-06-24 22:04* @desc**/ public class Case03 {/*** lambda表達式實現*/@Testpublic void test03() {MyMoney myMoney = new MyMoney(999888888);myMoney.printMoney(money -> new DecimalFormat("#,###").format(money));}@Testpublic void test04() {MyMoney myMoney = new MyMoney(8988888);Function<Integer, String> function = money -> new DecimalFormat("#,##").format(money);// 函數是接口的鏈式操作myMoney.printMoney(function.andThen(s -> {return "人民幣" + s;}));}}/*** 自定義類*/ class MyMoney {private int money;/*** 有參構造器* @param money*/public MyMoney(int money) {this.money = money;}/**** @param Function jdk1.8提供的函數接口*/public void printMoney(Function<Integer, String> function) {System.out.println("我的存款為:" + function.apply(this.money));} } View Code?
4 lambda表達式的寫法
4.1 概念
lambda表達式其實是實現了某個函數式接口的類的一個實例;
lambda表達式的箭頭左邊相當于函數式接口中未實現方法的入參,箭頭右邊相當于函數式接口中未實現方法的函數體;
lambda表達式就相當于函數式接口中那個未實現的方法的實現而已。
技巧01:編寫Lambda 表達式,實際是編寫函數式接口唯一的抽象方法的實現。因此,它是具備某種行為,或者說是具備某種功能的代碼單元,這樣的功能代碼,可以傳遞給方法的參數。
坑01:lambda 表達式是函數式接口的實現類實例,所以,定義 lambda 表達式,實際上要經歷兩件事情。第一件事情是定義函數式接口實現類,第二件事情是創建該實現類實例。 this 稱之為當前對象,但是, 定義 lambda 表達式時,也就是定義函數式接口實現類時, lambda 表達式代表的實現類本身沒有 this 對象,此時若是使用 this 對象,指的是把 lambda 表達式圍住的類的當前對象,而不是 lambda 表達式代表的實現類的當前對象。(源自:gitchat)
坑02:在lambda表達式使用了this關鍵字后,lambda表達式經過編譯過后的方法就是一個靜態方法;沒有使用this關鍵字時編譯過后就是一個普通的成員方法。
package demo05_webflux.chapter02;/*** @author 王楊帥* @create 2018-07-29 9:28* @desc Lambda表達式的4中寫法**/ public class Case04_LambdaDemo {public static void main(String[] args) {FuryInterface f1 = i -> i * 3;System.out.println(f1.result(20));System.out.println(f1.add(3, 44));FuryInterface f2 = (i) -> i * 3;FuryInterface f3 = (Integer i) -> i * 3;FuryInterface f4 = i -> {System.out.println("hello boy");return i * 3;};}}@FunctionalInterface interface FuryInterface {Integer result(Integer number);/*** Java8開始可以利用default關鍵字在接口中定義已經實現了的方法* @param a* @param b* @return*/default Integer add (Integer a, Integer b) {return a + b;} }/*** notes:* 1 函數式接口* 1.1 只有一個為實現方法的接口稱為函數式接口* 1.2 函數式接口也可以被實現,而且函數接口中的默認方法和為實現的方法都可以被實現* 1.3 函數式接口中的默認方法可以不在實現類中實現,但是函數式接口中的未實現方法必* 須在實現類中進行實現* 1.4 如果有兩個函數式接口的默認方法一樣,有一個接口同時繼承了這兩個接口,那么必須在* 接口中指明繼承的式哪一個父接口中的默認方法* 2 lambda表達式:* 2.1 lambda表達式其實是實現了某個函數式接口的類的一個實例* 2.2 lambda表達式的箭頭左邊相當于函數式接口中未實現方法的入參,* 箭頭右邊相當于函數式接口中未實現方法的函數體*/class test implements FuryInterface {@Overridepublic Integer result(Integer number) {return null;}@Overridepublic Integer add(Integer a, Integer b) {return null;} } View Code?
?
?
轉載于:https://www.cnblogs.com/NeverCtrl-C/p/9221300.html
總結
以上是生活随笔為你收集整理的Lambda01 编程范式、lambda表达式与匿名内部类、函数式接口、lambda表达式的写法...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux中crontab无法执行jav
- 下一篇: webpack入门系列2