最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java8之函數(shù)式接口及常用函數(shù)式接口講解

 更新時(shí)間:2022年11月21日 14:29:52   作者:代碼大師麥克勞瑞  
這篇文章主要介紹了Java8之函數(shù)式接口及常用函數(shù)式接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

函數(shù)式接口

1.概念

函數(shù)式接口(Functional Interface)就是一個(gè)有且僅有一個(gè)抽象方法,但是可以有多個(gè)非抽象方法的接口。

函數(shù)式接口可以被隱式轉(zhuǎn)換為 lambda 表達(dá)式。

Lambda 表達(dá)式和方法引用(實(shí)際上也可認(rèn)為是Lambda表達(dá)式)上。

2.@FunctionalInterface

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

我們常用的Runnable接口就是個(gè)典型的函數(shù)式接口,我們可以看到它有且僅有一個(gè)抽象方法run。并且可以看到一個(gè)注解@FunctionalInterface,這個(gè)注解的作用是強(qiáng)制你的接口只有一個(gè)抽象方法。

如果有多個(gè)話直接會(huì)報(bào)錯(cuò),如圖:

idea錯(cuò)誤提示:

編譯時(shí)錯(cuò)誤提示:

這里當(dāng)你寫(xiě)了第二個(gè)方法時(shí),編譯就無(wú)法通過(guò),idea甚至在編碼階段就行了提示。

3.函數(shù)式接口使用方式

我們直接上代碼,首先定義一個(gè)函數(shù)式接口

@FunctionalInterface
public interface SingleAbstraMethodInterface {
    public abstract void singleMethod();
}

我們定一個(gè)test類,封裝一個(gè)方法,將SingleAbstraMethodInterface當(dāng)做參數(shù)傳入方法,并打印一句話

public class Test {
    public void testMethod(SingleAbstraMethodInterface single){
        System.out.println("即將執(zhí)行函數(shù)式接口外部定義方法");
        single.singleMethod();
    }
    public static void main(String[] args) {
        Test test = new Test();
        test.testMethod(new SingleAbstraMethodInterface() {
            @Override
            public void singleMethod() {
                System.out.println("執(zhí)行函數(shù)式接口定義方法");
            }
        });
    }
}

執(zhí)行結(jié)果:

即將執(zhí)行函數(shù)式接口外部定義方法
執(zhí)行函數(shù)式接口定義方法

是不是和我們預(yù)期結(jié)果一樣。這個(gè)過(guò)程是不是有的同學(xué)已經(jīng)發(fā)現(xiàn),怎么這么像jdk里面的一些接口的使用,比如常用的Runnable接口。

我們來(lái)看看代碼。

public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("run方法執(zhí)行了");
            }
        }).start();
}

再看下Runnable接口源碼,是不是一樣

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

這時(shí),有的同學(xué)會(huì)說(shuō),我用Runnable接口可不是這么用的,我的寫(xiě)法比你優(yōu)雅,我是這么寫(xiě)的。

沒(méi)錯(cuò)函數(shù)式接口,函數(shù)式編程,我們可以使用lambda表達(dá)式的寫(xiě)法,可以讓代碼更優(yōu)雅,具體可以參照我的前一篇帖子。Java8之Lambda表達(dá)式

public static void main(String[] args) {
        new Thread(()-> {
           System.out.println("run方法執(zhí)行了");
        }).start();
}

常用函數(shù)式接口

1.JDK提供的函數(shù)式接口舉栗

java.lang.Runnable,
java.awt.event.ActionListener,
java.util.Comparator,
java.util.concurrent.Callable

java.util.function包下的接口,如Consumer、Predicate、Supplier等

其實(shí),jdk中給我們提供了很多的函數(shù)式接口,我們平時(shí)都會(huì)用到,只不過(guò)大家沒(méi)有注意到而已,這里我結(jié)合實(shí)際代碼講解幾個(gè)常用的函數(shù)式接口。想想大家平時(shí)常常用到stream流的各種方法來(lái)處理list。我看去stream類中看一下它提供的方法??梢钥吹接袔讉€(gè)出鏡率較高的函數(shù)式接口

  • Supplier
  • Comsumer
  • Predicate
  • Function

2.Supplier

@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     * @return a result
     */
    T get();
}

Supplier接口的get方法沒(méi)有入?yún)ⅲ祷匾粋€(gè)泛型T對(duì)象。

我們來(lái)看幾個(gè)使用 的實(shí)例。

先寫(xiě)一個(gè)實(shí)驗(yàn)對(duì)象girl,我們定義一個(gè)方法,創(chuàng)建對(duì)象,我們使用lambda的方式來(lái)調(diào)用并創(chuàng)建對(duì)象。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Girl {

    private String name;

    private Double size;

    private Double price;

    public static Girl create(final Supplier<Girl> supplier) {
        return supplier.get();
    }

    public static void main(String[] args) {
    	//創(chuàng)建對(duì)象
        Girl girl1 = Girl.create(Girl::new);
        Girl girl2 = Girl.create(()-> new Girl("lily",33d,1700d));
        Girl girl = null;
        //orElseGet
        Girl girl3 = Optional.ofNullable(girl).orElseGet(Girl::new);
    }
    
}

需要注意的是,我沒(méi)每調(diào)用一次get方法,都會(huì)重新創(chuàng)建一個(gè)對(duì)象

orElseGet方法入?yún)⑼瑯右彩荢upplier,這里對(duì)girl實(shí)例進(jìn)行判斷,通過(guò)Supplier實(shí)現(xiàn)了懶加載,也就是說(shuō)只有當(dāng)判斷girl為null時(shí),才會(huì)通過(guò)orElseGet方法創(chuàng)建新的對(duì)象并且返回。不得不說(shuō)這個(gè)設(shè)計(jì)是非常的巧妙。

3.Consumer

源碼如下:

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

可以看到accept方法接受一個(gè)對(duì)象,沒(méi)有返回值。

那么我們來(lái)實(shí)戰(zhàn),首先使用Lambda表達(dá)式聲明一個(gè)Supplier的實(shí)例,它是用來(lái)創(chuàng)建Girl實(shí)例;再使用Lambda表達(dá)式聲明一個(gè)Consumer的實(shí)例,它是用于打印出Girl實(shí)例的toString信息;最后Consumer消費(fèi)了Supplier生產(chǎn)的Girl。

我們常用的forEach方法入?yún)⒁彩荂onsumer。

使用代碼如下:

	Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);
	Consumer<Girl> consumer = (Girl g)->{
	   System.out.println(g.toString());
	};
	consumer.accept(supplier.get());
	ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
    list.forEach(System.out::println);

4.Predicate

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}

可以看到test方法接受一個(gè)對(duì)象,返回boolean類型,這個(gè)函數(shù)顯然是用來(lái)判斷真假。

那么我們用這個(gè)接口來(lái)構(gòu)造一個(gè)判斷女孩子條件的示例,還有我們常用的stream流中,filter的入?yún)⒁彩荘redicate,代碼如下:

		Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);
        Predicate<Girl> girl36d = (Girl g)-> Objects.equals(g.getSize(),36d);
        Predicate<Girl> girl33d = (Girl g)-> Objects.equals(g.getSize(),33d);
        boolean test33 = girl33d.test(supplier.get());
        boolean test36 = girl36d.test(supplier.get());
        System.out.println(supplier.get().getName() +"是否為[36d] :"+test36);
        System.out.println(supplier.get().getName() +"是否為[33d] :"+test33);

結(jié)果為:

lucy是否為[36d] :false
lucy是否為[33d] :true

		ArrayList<Girl> list = Lists.newArrayList();
        list.add(new Girl("露西", 33d, 2000d));
        list.add(new Girl("格蕾絲", 36d, 3000d));
        list.add(new Girl("安娜", 28d, 1500d));
        list.add(new Girl("克瑞斯", 31d, 1800d));
        Predicate<Girl> greaterThan30d = (Girl g)-> g.getSize()>=30d;
        list.stream().filter(greaterThan30d).forEach(System.out::println);

結(jié)果如下:

Girl(name=露西, size=33.0, price=2000.0)
Girl(name=格蕾絲, size=36.0, price=3000.0)
Girl(name=克瑞斯, size=31.0, price=1800.0)

5.Function

@FunctionalInterface
public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

這個(gè)看到apply接口接收一個(gè)泛型為T(mén)的入?yún)?,返回一個(gè)泛型為R的返回值,所以它的用途和Supplier還是略有區(qū)別。還是一樣我們舉個(gè)栗子用代碼來(lái)說(shuō)明:

Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);
 Function<Girl,String> girlMark = (Girl g)-> g.getName()+"的尺寸是"+g.getSize()+",每次能賺"+g.getPrice()+"。";
 System.out.println(girlMark.apply(supplier.get()));

我們可以看到funtion接口接收Girl對(duì)象實(shí)例,對(duì)girl的成員變量進(jìn)行拼接,返回girl的描述信息。其基本用法就是如此。

lucy的尺寸是33.0,每次能賺1700.0。

6.常用函數(shù)式接口相關(guān)擴(kuò)展接口

這里我列舉一些Supplier相關(guān)接口

a.Supplier相關(guān)拓展接口

接口名稱方法名稱方法簽名
Supplierget() -> T
BooleanSuppliergetAsBoolean() -> boolean
DoubleSuppliergetAsDouble() -> double
IntSuppliergetAsInt() -> int
LongSuppliergetAsLong() -> long

b.Comsumer相關(guān)拓展接口

接口名稱方法名稱方法簽名
Consumeraccept(T) -> void
DoubleConsumeraccept(double) -> void
IntConsumeraccept(int) -> void
LongConsumeraccept(long) -> void
ObjDoubleConsumeraccept(T, double) -> vo
ObjIntConsumeraccept(T, int) -> void
ObjLongConsumeraccept(T, long) -> void

c.Predicate相關(guān)拓展接口

接口名稱方法名稱方法簽名
Predicatetest(T) -> boolean
BiPredicatetest(T, U) -> boolean
DoublePredicatetest(double) -> bool
IntPredicatetest(int) -> boolean
LongPredicatetest(long) -> boolean

d.Function相關(guān)的接口

接口名稱方法名稱方法簽名
Functionapply(T) -> R
BiFunctionapply(T, U) -> R
DoubleFunctionapply(double) -> R
DoubleToIntFunctionapplyAsInt(double) -> int
DoubleToLongFunctionapplyAsLong(double) -> long
IntFunctionapply(int) -> R
IntToDoubleFunctionapplyAsDouble(int) -> double
IntToLongFunctionapplyAsLong(int) -> long
LongFunctionapply(long) -> R
LongToDoubleFunctionapplyAsDouble(long) -> double
LongToIntFunctionapplyAsInt(long) -> int
ToDoubleFunctionapplyAsDouble(T) -> double
ToDoubleBiFunctionapplyAsDouble(T, U) -> double
ToIntFunctionapplyAsInt(T) -> int
ToIntBiFunctionapplyAsInt(T, U) -> int
ToLongFunctionapplyAsLong(T) -> long
ToLongBiFunctionapplyAsLong(T, U) -> long

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java新特性之Nashorn_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java新特性之Nashorn_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java新特性之Nashorn的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 詳解JAVA中ListIterator和Iterator的辨析

    詳解JAVA中ListIterator和Iterator的辨析

    這篇文章主要為大家詳細(xì)介紹了JAVAListIterator和Iterator的辨析,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • 從入門(mén)到超神進(jìn)階的Netty群聊系統(tǒng)

    從入門(mén)到超神進(jìn)階的Netty群聊系統(tǒng)

    本篇文章基于Netty做一個(gè)聊天室案例加強(qiáng)Netty的熟練度,案例的效果是服務(wù)端可以廣播某客戶端的消息給所有客戶端。每個(gè)客戶端監(jiān)聽(tīng)鍵盤(pán)輸入來(lái)獲取消息,然后發(fā)送給服務(wù)端
    2021-08-08
  • 如何手寫(xiě)一個(gè)Spring Boot Starter

    如何手寫(xiě)一個(gè)Spring Boot Starter

    這篇文章主要介紹了如何手寫(xiě)一個(gè)Spring Boot Starter,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • Java import static及import原理區(qū)別解析

    Java import static及import原理區(qū)別解析

    這篇文章主要介紹了Java import static及import原理區(qū)別解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Spring @Primary作用和實(shí)現(xiàn)原理詳解

    Spring @Primary作用和實(shí)現(xiàn)原理詳解

    今天分享一下Spring中的@Primary注解,Primary的意思是主要的,我們?cè)谑褂胹pring的時(shí)候,難免會(huì)定義多個(gè)類型相同的bean,這時(shí)候如果不采取一些方法,那么是無(wú)法正常使用bean的,所以本就給大家介紹Spring @Primary的作用和實(shí)現(xiàn)原理
    2023-07-07
  • Mybatis中自定義TypeHandler處理枚舉詳解

    Mybatis中自定義TypeHandler處理枚舉詳解

    本文主要介紹了Mybatis中自定義TypeHandler處理枚舉的相關(guān)知識(shí)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • Java中字符串替換的四種方法舉例總結(jié)

    Java中字符串替換的四種方法舉例總結(jié)

    Java提供了多種方法來(lái)替換字符串,其中最常用的是使用replace()方法和正則表達(dá)式,下面這篇文章主要給大家介紹了關(guān)于Java中字符串替換的四種方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • Springboot如何集成websocket

    Springboot如何集成websocket

    這篇文章主要介紹了Springboot如何集成websocket問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java 實(shí)現(xiàn)簡(jiǎn)單靜態(tài)資源Web服務(wù)器的示例

    Java 實(shí)現(xiàn)簡(jiǎn)單靜態(tài)資源Web服務(wù)器的示例

    這篇文章主要介紹了Java 實(shí)現(xiàn)簡(jiǎn)單靜態(tài)資源Web服務(wù)器的示例,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-11-11

最新評(píng)論

洛隆县| 都江堰市| 龙陵县| 贵德县| 武清区| 鹿泉市| 辽宁省| 鲁山县| 泗阳县| 嘉鱼县| 西充县| 金乡县| 酒泉市| 阿鲁科尔沁旗| 红桥区| 肃北| 察隅县| 东至县| 岳阳市| 离岛区| 晋宁县| 和林格尔县| 南川市| 泗洪县| 龙州县| 定南县| 莒南县| 广饶县| 芜湖县| 桃园市| 江川县| 丹凤县| 台中县| 福建省| 株洲市| 华容县| 卢龙县| 桑日县| 天镇县| 山阳县| 嘉禾县|