Java?Lambda表達(dá)式常用的函數(shù)式接口
前言:
在Java8支持Lambda表達(dá)式以后,為了滿足Lambda
表達(dá)式的一些典型使用場景,JDK為我們提供了大量常用的函數(shù)式接口。它們主要在 java.util.function
包中,下面簡單介紹幾個(gè)其中的接口及其使用示例。
Supplier接口
Supplier
接口是對象實(shí)例的提供者,定義了一個(gè)名叫get
的抽象方法,它沒有任何入?yún)?,并返回一個(gè)泛型T對象,具體源碼如下:
package java.util.function; @FunctionalInterface public interface Supplier<T> { T get(); }
源碼比較簡單,我們來個(gè)例子。這是之前提過的表示口罩的類:
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
表達(dá)式聲明一個(gè)Supplier
的實(shí)例:
Supplier<Mask> supplier = () -> new Mask("3M", "N95");
用它來創(chuàng)建品牌為3M、類型為N95的Mask
實(shí)例:
Mask mask = supplier.get(); System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());
運(yùn)行結(jié)果如下:
Brand: 3M, Type: N95
特別需要注意的是,本例中每一次調(diào)用get
方法都會(huì)創(chuàng)建新的對象。
Consumer接口
Consumer
接口是一個(gè)類似消費(fèi)者的接口,定義了一個(gè)名叫accept
的抽象方法,它的入?yún)⑹且粋€(gè)泛型T對象,沒有任何返回(void),主要源碼如下:
package java.util.function; @FunctionalInterface public interface Consumer<T> { void accept(T t); }
結(jié)合上面的Supplier
接口,我們來個(gè)例子:
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表達(dá)式聲明一個(gè)Supplier
的實(shí)例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask
實(shí)例;再使用Lambda表達(dá)式聲明一個(gè)Consumer
的實(shí)例,它是用于打印出Mask
實(shí)例的相關(guān)信息;最后Consumer
消費(fèi)了Supplier
生產(chǎn)的Mask
。
運(yùn)行結(jié)果如下:
Brand: 3M, Type: N95
Predicate接口
Predicate
接口是判斷是與否的接口,定義了一個(gè)名叫test
的抽象方法,它的入?yún)⑹且粋€(gè)泛型T對象,并返回一個(gè)boolean類型,主要源碼如下:
package java.util.function; @FunctionalInterface public interface Predicate<T> { boolean test(T t); }
結(jié)合上面的Supplier
接口,我們來個(gè)例子:
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表達(dá)式聲明一個(gè)Supplier
的實(shí)例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask
實(shí)例;再使用Lambda表達(dá)式聲明一個(gè)Predicate
的實(shí)例n95,它是用于判斷是否為N95口罩;再使用Lambda表達(dá)式聲明一個(gè)Predicate
的實(shí)例kn95,它是用于判斷是否為KN95口罩;最后分別用兩個(gè)Predicate
判斷Supplier
生產(chǎn)的Mask
。
運(yùn)行結(jié)果如下:
是否為N95口罩:true
是否為KN95口罩:false
Function接口
Function
接口是對實(shí)例進(jìn)行處理轉(zhuǎn)換的接口,定義了一個(gè)名叫apply
的抽象方法,它的入?yún)⑹且粋€(gè)泛型T對象,并返回一個(gè)泛型R對象,主要源碼如下:
package java.util.function; @FunctionalInterface public interface Function<T, R> { R apply(T t); }
結(jié)合上面的Supplier
接口,我們來個(gè)例子:
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表達(dá)式聲明一個(gè)Supplier
的實(shí)例,它是用來創(chuàng)建品牌為3M、類型為N95的Mask
實(shí)例;再使用Lambda表達(dá)式聲明一個(gè)Function
的實(shí)例brand,它是用于獲取口罩的品牌;再使用Lambda表達(dá)式聲明一個(gè)Function
的實(shí)例type,它是用于獲取口罩的類型;最后分別用兩個(gè)Function
分析Supplier
生產(chǎn)的Mask
。
運(yùn)行結(jié)果如下:
口罩品牌:3M
口罩類型:N95
BiFunction接口
Function
接口的入?yún)⒅挥幸粋€(gè)泛型對象,JDK還為我們提供了兩個(gè)泛型對象入?yún)⒌慕涌冢?code>BiFunction接口,主要源碼如下:
package java.util.function; @FunctionalInterface public interface BiFunction<T, U, R> { R apply(T t, U u); }
我們可以用BiFunction
接口傳入兩個(gè)String
直接創(chuàng)建Mask
實(shí)例:
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());
運(yùn)行結(jié)果如下:
Brand: 3M, Type: N95
基本數(shù)據(jù)類型
以上介紹的幾個(gè)常用的函數(shù)式接口入?yún)⒑头祷?,都是泛型對象的,也就是必須為引用類型。?dāng)我們傳入或獲取的是基本數(shù)據(jù)類型時(shí),將會(huì)發(fā)生自動(dòng)裝箱和自動(dòng)拆箱,帶來不必要的性能損耗,比如:
Supplier<Long> supplier = () -> System.currentTimeMillis(); long timeMillis = supplier.get();
在上面例子里,發(fā)生了一次自動(dòng)裝箱(long被裝箱為Long)和一次自動(dòng)拆箱(Long被拆箱為long),如何避免這種不必要的性能損耗呢?JDK為我們提供相應(yīng)的函數(shù)式接口,如LongSupplier
接口,定義了一個(gè)名叫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表達(dá)式常用的函數(shù)式接口的文章就介紹到這了,更多相關(guān)Lambda函數(shù)式接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)之java實(shí)現(xiàn)棧
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)棧,需要的朋友可以參考下2014-03-03Spring中allowedOriginPatterns和allowedOrigins方法有何不同詳解
這篇文章主要給大家介紹了關(guān)于Spring中allowedOriginPatterns和allowedOrigins方法有何不同,allowedOriginPatterns和allowedOrigins都是用來設(shè)置允許跨域請求的來源,需要的朋友可以參考下2023-10-10在IDEA中 實(shí)現(xiàn)給main方法附帶參數(shù)的操作
這篇文章主要介紹了在IDEA中 實(shí)現(xiàn)給main方法附帶參數(shù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01使用feign服務(wù)調(diào)用添加Header參數(shù)
這篇文章主要介紹了使用feign服務(wù)調(diào)用添加Header參數(shù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06java實(shí)現(xiàn)微信小程序加密數(shù)據(jù)解密算法
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)微信小程序加密數(shù)據(jù)解密算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09mybatis?獲取更新(update)記錄的id之<selectKey>用法說明
這篇文章主要介紹了mybatis?獲取更新(update)記錄的id之<selectKey>用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Java編程實(shí)現(xiàn)調(diào)用com操作Word方法實(shí)例代碼
這篇文章主要介紹了Java編程實(shí)現(xiàn)調(diào)用com操作Word方法實(shí)例代碼,代碼注釋很詳細(xì),在這里分給大家,需要的朋友可以參考下。2017-09-09