Java?Lambda表達式常用的函數(shù)式接口
前言:
在Java8支持Lambda表達式以后,為了滿足Lambda表達式的一些典型使用場景,JDK為我們提供了大量常用的函數(shù)式接口。它們主要在 java.util.function 包中,下面簡單介紹幾個其中的接口及其使用示例。
Supplier接口
Supplier接口是對象實例的提供者,定義了一個名叫get的抽象方法,它沒有任何入?yún)?,并返回一個泛型T對象,具體源碼如下:
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
源碼比較簡單,我們來個例子。這是之前提過的表示口罩的類:
package one.more.study;
/**
* 口罩
*/
public class Mask {
public Mask(String brand, String type) {
this.brand = brand;
this.type = type;
}
/**
* 品牌
*/
private String brand;
/**
* 類型
*/
private String type;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
下面我們使用Lambda表達式聲明一個Supplier的實例:
Supplier<Mask> supplier = () -> new Mask("3M", "N95");
用它來創(chuàng)建品牌為3M、類型為N95的Mask實例:
Mask mask = supplier.get();
System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());
運行結(jié)果如下:
Brand: 3M, Type: N95
特別需要注意的是,本例中每一次調(diào)用get方法都會創(chuàng)建新的對象。
Consumer接口
Consumer接口是一個類似消費者的接口,定義了一個名叫accept的抽象方法,它的入?yún)⑹且粋€泛型T對象,沒有任何返回(void),主要源碼如下:
package java.util.function;
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
結(jié)合上面的Supplier接口,我們來個例子:
Supplier<Mask> supplier = () -> new Mask("3M", "N95");
Consumer<Mask> consumer = (Mask mask) -> {
System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());
};
consumer.accept(supplier.get());
首先使用Lambda表達式聲明一個Supplier的實例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask實例;再使用Lambda表達式聲明一個Consumer的實例,它是用于打印出Mask實例的相關(guān)信息;最后Consumer消費了Supplier生產(chǎn)的Mask。
運行結(jié)果如下:
Brand: 3M, Type: N95
Predicate接口
Predicate接口是判斷是與否的接口,定義了一個名叫test的抽象方法,它的入?yún)⑹且粋€泛型T對象,并返回一個boolean類型,主要源碼如下:
package java.util.function;
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
結(jié)合上面的Supplier接口,我們來個例子:
Supplier<Mask> supplier = () -> new Mask("3M", "N95");
Predicate<Mask> n95 = (Mask mask) -> "N95".equals(mask.getType());
Predicate<Mask> kn95 = (Mask mask) -> "KN95".equals(mask.getType());
System.out.println("是否為N95口罩:" + n95.test(supplier.get()));
System.out.println("是否為KN95口罩:" + kn95.test(supplier.get()));
首先使用Lambda表達式聲明一個Supplier的實例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask實例;再使用Lambda表達式聲明一個Predicate的實例n95,它是用于判斷是否為N95口罩;再使用Lambda表達式聲明一個Predicate的實例kn95,它是用于判斷是否為KN95口罩;最后分別用兩個Predicate判斷Supplier生產(chǎn)的Mask。
運行結(jié)果如下:
是否為N95口罩:true
是否為KN95口罩:false
Function接口
Function接口是對實例進行處理轉(zhuǎn)換的接口,定義了一個名叫apply的抽象方法,它的入?yún)⑹且粋€泛型T對象,并返回一個泛型R對象,主要源碼如下:
package java.util.function;
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
結(jié)合上面的Supplier接口,我們來個例子:
Supplier<Mask> supplier = () -> new Mask("3M", "N95");
Function<Mask, String> brand = (Mask mask) -> mask.getBrand();
Function<Mask, String> type = (Mask mask) -> mask.getType();
System.out.println("口罩品牌:" + brand.apply(supplier.get()));
System.out.println("口罩類型:" + type.apply(supplier.get()));
首先使用Lambda表達式聲明一個Supplier的實例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask實例;再使用Lambda表達式聲明一個Function的實例brand,它是用于獲取口罩的品牌;再使用Lambda表達式聲明一個Function的實例type,它是用于獲取口罩的類型;最后分別用兩個Function分析Supplier生產(chǎn)的Mask。
運行結(jié)果如下:
口罩品牌:3M
口罩類型:N95
BiFunction接口
Function接口的入?yún)⒅挥幸粋€泛型對象,JDK還為我們提供了兩個泛型對象入?yún)⒌慕涌冢?code>BiFunction接口,主要源碼如下:
package java.util.function;
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
我們可以用BiFunction接口傳入兩個String直接創(chuàng)建Mask實例:
BiFunction<String,String,Mask> biFunction = (String brand, String type) -> new Mask(brand, type);
Mask mask = biFunction.apply("3M", "N95");
System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());
運行結(jié)果如下:
Brand: 3M, Type: N95
基本數(shù)據(jù)類型
以上介紹的幾個常用的函數(shù)式接口入?yún)⒑头祷?,都是泛型對象的,也就是必須為引用類型。當我們傳入或獲取的是基本數(shù)據(jù)類型時,將會發(fā)生自動裝箱和自動拆箱,帶來不必要的性能損耗,比如:
Supplier<Long> supplier = () -> System.currentTimeMillis(); long timeMillis = supplier.get();
在上面例子里,發(fā)生了一次自動裝箱(long被裝箱為Long)和一次自動拆箱(Long被拆箱為long),如何避免這種不必要的性能損耗呢?JDK為我們提供相應(yīng)的函數(shù)式接口,如LongSupplier接口,定義了一個名叫getAsLong的抽象方法,簽名是() -> long。
上面的例子可以優(yōu)化為:
LongSupplier supplier = () -> System.currentTimeMillis(); long timeMillis = supplier.getAsLong();
類似這樣的接口還有很多,我為大家整理了一下:
Supplier相關(guān)的接口
| 接口名稱 | 方法名稱 | 方法簽名 |
|---|---|---|
| Supplier | get | () -> T |
| BooleanSupplier | getAsBoolean | () -> boolean |
| DoubleSupplier | getAsDouble | () -> double |
| IntSupplier | getAsInt | () -> int |
| LongSupplier | getAsLong | () -> long |
Consumer相關(guān)的接口
| 接口名稱 | 方法名稱 | 方法簽名 |
|---|---|---|
| Consumer | accept | (T) -> void |
| DoubleConsumer | accept | (double) -> void |
| IntConsumer | accept | (int) -> void |
| LongConsumer | accept | (long) -> void |
| ObjDoubleConsumer | accept | (T, double) -> void |
| ObjIntConsumer | accept | (T, int) -> void |
| ObjLongConsumer | accept | (T, long) -> void |
Predicate相關(guān)的接口
| 接口名稱 | 方法名稱 | 方法簽名 |
|---|---|---|
| Predicate | test | (T) -> boolean |
| BiPredicate | test | (T, U) -> boolean |
| DoublePredicate | test | (double) -> boolean |
| IntPredicate | test | (int) -> boolean |
| LongPredicate | test | (long) -> boolean |
Function相關(guān)的接口
| 接口名稱 | 方法名稱 | 方法簽名 |
|---|---|---|
| Function | apply | (T) -> R |
| BiFunction | apply | (T, U) -> R |
| DoubleFunction | apply | (double) -> R |
| DoubleToIntFunction | applyAsInt | (double) -> int |
| DoubleToLongFunction | applyAsLong | (double) -> long |
| IntFunction | apply | (int) -> R |
| IntToDoubleFunction | applyAsDouble | (int) -> double |
| IntToLongFunction | applyAsLong | (int) -> long |
| LongFunction | apply | (long) -> R |
| LongToDoubleFunction | applyAsDouble | (long) -> double |
| LongToIntFunction | applyAsInt | (long) -> int |
| ToDoubleFunction | applyAsDouble | (T) -> double |
| ToDoubleBiFunction | applyAsDouble | (T, U) -> double |
| ToIntFunction | applyAsInt | (T) -> int |
| ToIntBiFunction | applyAsInt | (T, U) -> int |
| ToLongFunction | applyAsLong | (T) -> long |
| ToLongBiFunction | applyAsLong | (T, U) -> long |
到此這篇關(guān)于Java Lambda表達式常用的函數(shù)式接口的文章就介紹到這了,更多相關(guān)Lambda函數(shù)式接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Tomcat數(shù)據(jù)源配置方法_JBuilder中
今天幫一同事配置一個數(shù)據(jù)源,采用tomcat5.5.9,本來是個很簡單的事,以前也配過,但由于很長時間沒用過容器提供的數(shù)據(jù)源了(IOC用慣了),也只記的個大概了,所以剛開始一配就出錯了,google了一下,有很多資料,照著試試卻都不好使(到不是別人說的不對,只是大家用的版本不同)。2008-10-10
Spring Security使用權(quán)限注解實現(xiàn)精確控制
在現(xiàn)代的應(yīng)用系統(tǒng)中,權(quán)限管理是確保系統(tǒng)安全性的重要環(huán)節(jié),Spring Security作為Java世界最為普及的安全框架,提供了強大而靈活的權(quán)限控制功能,這篇文章將深入探討Spring Security使用權(quán)限注解實現(xiàn)精確控制,需要的朋友可以參考下2024-12-12
Spring?Cloud?OpenFeign模版化客戶端搭建過程
OpenFeign是一個顯示聲明式的WebService客戶端。使用OpenFeign能讓編寫Web Service客戶端更加簡單,這篇文章主要介紹了Spring?Cloud?OpenFeign模版化客戶端,需要的朋友可以參考下2022-06-06
JavaWeb三大組件之監(jiān)聽器Listener詳解
這篇文章主要介紹了JavaWeb三大組件之監(jiān)聽器Listener詳解,在JavaWeb應(yīng)用程序中,Listener監(jiān)聽器是一種機制,用于監(jiān)聽和響應(yīng)特定的事件,它可以感知并響應(yīng)與應(yīng)用程序相關(guān)的事件,從而執(zhí)行相應(yīng)的邏輯處理,需要的朋友可以參考下2023-10-10
2022年最新java?8?(?jdk1.8u321)安裝圖文教程
這篇文章主要介紹了2022年最新java?8?(?jdk1.8u321)安裝圖文教程,截止2022年1月,官方出的jdk1.8目前已更新到8u321的版本,本文通過圖文并茂的形式給大家介紹安裝過程,需要的朋友可以參考下2022-08-08
Spring將MultipartFile轉(zhuǎn)存到本地磁盤的三種方式
在Java中處理文件向來是一種不是很方便的操作,然后隨著Spring框架的崛起,使用Spring框架中的MultipartFile來處理文件也是件很方便的事了,今天就給大家介紹Spring將MultipartFile轉(zhuǎn)存到本地磁盤的方式,需要的朋友可以參考下2024-10-10

