欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java之函數(shù)式接口解讀

 更新時間:2023年03月01日 09:48:20   作者:你好y  
這篇文章主要介紹了java之函數(shù)式接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

一、函數(shù)式接口

概念

函數(shù)式接口在Java中是指:有且僅有一個抽象方法的接口。 當然接口中可以包含其他的方法(默認,靜態(tài),私有)

函數(shù)式接口,即適用于函數(shù)式編程場景的接口。而Java中的函數(shù)式編程體現(xiàn)就是Lambda,所以函數(shù)式接口就是可

以適用于Lambda使用的接口。只有確保接口中有且僅有一個抽象方法,Java中的Lambda才能順利地進行推導。

備注:“語法糖”是指使用更加方便,但是原理不變的代碼語法。例如在遍歷集合時使用的for-each語法,其實底層的實現(xiàn)原理仍然是迭代器,這便是“語法糖”。從應用層面來講,Java中的Lambda可以被當做是匿名內(nèi)部類的“語法糖”,但是二者在原理上是不同的。

格式

只要確保接口中有且僅有一個抽象方法即可:

修飾符 interface 接口名稱 {
public abstract 返回值類型 方法名稱(可選參數(shù)信息);

// 其他非抽象方法內(nèi)容

}

@FunctionalInterface注解

與 @Override 注解的作用類似,Java 8中專門為函數(shù)式接口引入了一個新的注解: @FunctionalInterface 。該注

解可用于一個接口的定義上:

  • 一旦使用該注解來定義接口,編譯器將會強制檢查該接口是否確實有且僅有一個抽象方法,否則將會報錯。需要
  • 的是,即使不使用該注解,只要滿足函數(shù)式接口的定義,這仍然是一個函數(shù)式接口,使用起來都一樣。

作用:可以檢測接口是否是一個函數(shù)式接口

  • 是:編譯成功 否:編譯失?。ń涌谥袥]有抽象方法或者抽象方法的個數(shù)多于一個)
  • 函數(shù)式接口的使用:一般作為方法的參數(shù)和返回值類型

當參數(shù)是一個接口時,我們可以采用下面三種方法來進行操作

image-20210712144949790

性能浪費的日志案例

注:日志可以幫助我們快速的定位問題,記錄程序運行過程中的情況,以便項目的監(jiān)控和優(yōu)化。

一種典型的場景就是對參數(shù)進行有條件使用,例如對日志消息進行拼接后,在滿足條件的情況下進行打印輸出:

image-20210712150811186

發(fā)現(xiàn)以下代碼存在的一些性能浪費的問題:

調(diào)用showLog方法,傳遞的第二個參數(shù)是一個拼接后的字符串,先把字符串拼接好,然后在調(diào)用showlog方法,showLog方法中如果傳遞的日志等級不是1級,那么就不會是如此拼接后的字符串,所以感覺字符串就白拼接了,存在了浪費.

使用Lambda優(yōu)化日志案例

Lambda的特點:延遲加載

Lambda的使用前提,必須存在函數(shù)式接口

使用Lambda必然需要一個函數(shù)式接口:

然后對 log 方法進行改造:

@FunctionalInterface 

public interface MessageBuilder { 

String buildMessage(); 

}

對 log 方法進行改造:

public class Demo02LoggerLambda { 

private static void log(int level, MessageBuilder builder) { 

if (level == 1) { 

System.out.println(builder.buildMessage()); 

	} 
}
public static void main(String[] args) { 
    String msgA = "Hello"; 
    String msgB = "World"; 
    String msgC = "Java"; 
    log(1, () ‐> msgA + msgB + msgC ); 
} 
}

這樣一來,只有當級別滿足要求的時候,才會進行三個字符串的拼接;否則三個字符串將不會進行拼接。

  • 使用Lambda表達式作為參數(shù)傳遞,僅僅是把參數(shù)傳遞到showLog方法中。
  • 只有滿足條件,日志的等級是1級,才會調(diào)用接口MessageBuilder中的方法builderMessage,才會進行字符串的拼接。如果條件不滿足,日志的等級不是1級
  • 那么MessageBuilder接口中的方法builderMessage也不會執(zhí)行
  • 所以拼接字符串的代碼也不會執(zhí)行
  • 所以不會存在性能的浪費

使用Lambda作為參數(shù)和返回值

如果拋開實現(xiàn)原理不說,Java中的Lambda表達式可以被當作是匿名內(nèi)部類的替代品。如果方法的參數(shù)是一個函數(shù) 式接口類型,那么就可以使用Lambda表達式進行替代。

使用Lambda表達式作為方法參數(shù),其實就是使用函數(shù)式 接口作為方法參數(shù)。

例如 java.lang.Runnable 接口就是一個函數(shù)式接口,假設有一個 startThread 方法使用該接口作為參數(shù),那么就 可以使用Lambda進行傳參。

這種情況其實和 Thread 類的構(gòu)造方法參數(shù)為 Runnable 沒有本質(zhì)區(qū)別。

public class Demo04Runnable {
    private static void startThread(Runnable task) { 
        new Thread(task).start(); }
    
    public static void main(String[] args) { 
        startThread(() ‐> System.out.println("線程任務執(zhí)行!"));
    } 
}

Lambda表達式作為參數(shù)傳遞

使用前提:方法的參數(shù)必須時函數(shù)式接口(是接口且接口中有且只有一個抽象方法)

image-20210712152443239

Lambda表達式作為返回值

如果一個方法的返回值類型是一個函數(shù)式接口,那么就可以直接返回一個Lambda表達式。

當需要通過一 個方法來獲取一個 java.util.Comparator 接口類型的對象作為排序器時,就可以調(diào)該方法獲取。

package com.itheima.demo01.Lambda;

import java.util.Arrays;
import java.util.Comparator;

public class Demo01 {
    //定義一個方法,方法的返回值類型使用函數(shù)式接口Comparator
    public static Comparator<String> getComparator(){
        //方法的返回值類型是一個接口,那么我們可以返回這個接口的匿名內(nèi)部類
       /* return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照字符串的降序排序
                return o2.length()-o1.length();
            }
        };*/
       
       //使用lambda表達式進行優(yōu)化
        return ( o1,  o2)-> o2.length()-o1.length();
    }
    public static void main(String[] args) {
        String[] arr={"aaaa","nnnnnnn","oooooooo"};
        System.out.println("排序前:");
        System.out.println(Arrays.toString(arr));

        System.out.println("排序后:");
        Arrays.sort(arr,getComparator());
        System.out.println(Arrays.toString(arr));



    }
}

二、常用函數(shù)式接口

JDK提供了大量常用的函數(shù)式接口以豐富Lambda的典型使用場景,它們主要在 java.util.function 包中被提供。

下面是最簡單的幾個接口及使用示例。

Supplier接口

java.util.function.Supplier 接口僅包含一個無參的方法: T get() 。用來獲取一個泛型參數(shù)指定類型的對象數(shù)據(jù)。由于這是一個函數(shù)式接口,這也就意味著對應的Lambda表達式需要“對外提供”一個符合泛型類型的對象數(shù)據(jù)。

Supplier接口被稱之為生產(chǎn)型接口,指定接口的泛型是什么類型,那么接口中的get方法就會生產(chǎn)什么類型的數(shù)據(jù)

image-20210712154951738

練習:求數(shù)組元素最大值

題目

使用 Supplier 接口作為方法參數(shù)類型,通過Lambda表達式求出int數(shù)組中的最大值。提示:接口的泛型請使用 java.lang.Integer 類。

package com.itheima.demo01.Lambda;

import java.util.function.Supplier;

public class Demo02Test {
    //定義一個方法,方法的參數(shù)傳遞Supplier,泛型使用Integer
    public static Integer  getMax(Supplier<Integer> sup){
        return sup.get();
    }
    public static void main(String[] args) {
        int[] arr={12,9,8,3,30};
        //調(diào)用getMax方法,方法的參數(shù)Supplier是一個函數(shù)式接口,所以可以傳遞Lambda表達式
        int maxValue=getMax(()->{
            int max=arr[0];
            for (int i = 0; i <arr.length ; i++) {
                if (max<arr[i]){
                    max=arr[i];
                }
            }
            return max;

        });
        System.out.println(maxValue);


    }
}

Consumer接口

java.util.function.Consumer 接口則正好與Supplier接口相反,它不是生產(chǎn)一個數(shù)據(jù),而是消費一個數(shù)據(jù)(至于具體怎么消費(使用), 需要自定義(輸出,計算…) 其數(shù)據(jù)類型由泛型決定。

抽象方法:accept

Consumer 接口中包含抽象方法 void accept(T t) ,意為消費一個指定泛型的數(shù)據(jù)?;臼褂萌纾?/p>

package com.itheima.demo01.Lambda;

import java.util.function.Consumer;

public class Demo03Consumer {
    /*定義一個方法
方法的參數(shù)傳遞一個字符串的姓名
方法的參數(shù)傳遞Consumer接口,泛型使用String
可以使用Consumer接口消費字符串的姓名*/
    public static void method(String name,Consumer<String> con){
        con.accept(name);
    }

    public static void main(String[] args) {
     //調(diào)用method方法,傳遞字符串姓名,方法的另一個參數(shù)是Consumer接口,是一個函數(shù)式接口,所以可以傳遞Lombda表達式
        method("不放棄",(String name)->{
            //1.最簡單的消費,直接輸出
            System.out.println(name);
            //2.消費方式:把字符串進行翻轉(zhuǎn)輸出
            
            //StringBuffer里面有個字符反轉(zhuǎn)的方法
            String s=new StringBuffer(name).reverse().toString();
            System.out.println(s);
        });
    }
}

默認方法:andThen

如果一個方法的參數(shù)和返回值全都是 Consumer 類型,那么就可以實現(xiàn)效果:消費數(shù)據(jù)的時候,首先做一個操作,

然后再做一個操作,實現(xiàn)組合。而這個方法就是 Consumer 接口中的default方法 andThen 。

image-20210712162839420

要想實現(xiàn)組合,需要兩個或多個Lambda表達式即可,而 andThen 的語義正是“一步接一步”操作。例如兩個步驟組

合的情況:

package com.itheima.demo01.Lambda;

import java.util.function.Consumer;

public class Demo04 {
    ///定義一個方法,方法的參數(shù)傳遞一個字符串和兩個Consumer接口, Consumer接口的泛型使用字符串
    public static void method(String s, Consumer<String> con1,Consumer<String> con2){
       // con1.accept(s);
        //con2.accept(s);
        con1.andThen(con2).accept(s);//con1連接con2,先執(zhí)行con1消費數(shù)據(jù),再執(zhí)行con2消費數(shù)據(jù)
    }

    public static void main(String[] args) {
        method("BeiJing",
                (s)->{
                //消費方式:將字符串變成小寫
                    System.out.println(s.toLowerCase());
                },
                (s)->{
                 //消費方式:將字符串變成大寫
                    System.out.println(s.toUpperCase());

                }
                );
    }

}

練習:格式化打印信息

題目

下面的字符串數(shù)組當中存有多條信息,請按照格式“ 姓名:XX。性別:XX。 ”的格式將信息打印出來。要求將打印姓

名的動作作為第一個 Consumer 接口的Lambda實例,將打印性別的動作作為第二個 Consumer 接口的Lambda實

例,將兩個 Consumer 接口按照順序“拼接”到一起。

public static void main(String[] args) { 

String[] array = { "迪麗熱巴,女", "古力娜扎,女", "馬爾扎哈,男" }; 

}

代碼演示:

package com.itheima.demo01.Lambda;

import java.util.function.Consumer;

public class Demo05Test {
    public static void method(String[] arr, Consumer<String> con1,Consumer<String> con2){
        //遍歷字符串數(shù)組
        for (String s : arr) {
            //使用andThen方法連接連個Consume接口,消費字符串
            con1.andThen(con2).accept(s);
        }
    }

    public static void main(String[] args) {
        String[] arr={"迪麗熱巴,女", "古力娜扎,女", "馬爾扎哈,男"};
        method(arr,
                (t)->{
                    //將字符串數(shù)據(jù)進行切割
                    String name = t.split(",")[0];
                    //消費一:打印出姓名:XXX
                    System.out.print("姓名:"+name);
                },
                (t)->{
                    //將字符串數(shù)據(jù)進行切割
                    String age = t.split(",")[1];
                    //消費二:打印出性別:XXX
                    System.out.println(","+"年齡:"+age+"。");


                });
    }
}

image-20210712170009157

Predicate接口

有時候我們需要對某種類型的數(shù)據(jù)進行判斷,從而得到一個boolean值結(jié)果。這時可以使用

java.util.function.Predicate 接口。

抽象方法:test

Predicate 接口中包含一個抽象方法: boolean test(T t) 。用于條件判斷的場景:

import java.util.function.Predicate; 
public class Demo15PredicateTest { 
    private static void method(Predicate<String> predicate) { 
        boolean veryLong = predicate.test("HelloWorld"); 
        System.out.println("字符串很長嗎:" + veryLong); }
    public static void main(String[] args) { 
        method(s ‐> s.length() > 5); 
    }
}

條件判斷的標準是傳入的Lambda表達式邏輯,只要字符串長度大于5則認為很長。

默認方法:and

相當于&&

既然是條件判斷,就會存在與、或、非三種常見的邏輯關系。其中將兩個 Predicate 條件使用“與”邏輯連接起來實

現(xiàn)“并且”的效果時,可以使用default方法 and 。

如果要判斷一個字符串既要包含大寫“H”,又要包含大寫“W”,那么:

import java.util.function.Predicate; 
public class Demo16PredicateAnd { 
    private static void method(Predicate<String> one, Predicate<String> two) {
        boolean isValid = one.and(two).test("Helloworld"); 
        System.out.println("字符串符合要求嗎:" + isValid); 
    }
    public static void main(String[] args) { 
        method(s ‐> s.contains("H"), s ‐> s.contains("W")); 
    }
}

默認方法:or

與 and 的“與”類似,默認方法 or 實現(xiàn)邏輯關系中的“”。

如果希望實現(xiàn)邏輯“字符串包含大寫H或者包含大寫W”,那么代碼只需要將“and”修改為“or”名稱即可,其他都不變:

import java.util.function.Predicate; 
public class Demo16PredicateAnd { 
    private static void method(Predicate<String> one, Predicate<String> two) { 
        boolean isValid = one.or(two).test("Helloworld"); 
        System.out.println("字符串符合要求嗎:" + isValid); 
    }
    public static void main(String[] args) {
        method(s ‐> s.contains("H"), s ‐> s.contains("W"));
    }
}

默認方法:negate

“與”、“或”已經(jīng)了解了,剩下的“非”(取反)也會簡單。

從實現(xiàn)中很容易看出,它是執(zhí)行了test方法之后,對結(jié)果boolean值進行“!”取反而已。一定要在 test 方法調(diào)用之前

調(diào)用 negate 方法,正如 and 和 or 方法一樣:

import java.util.function.Predicate; 
public class Demo17PredicateNegate { 
    private static void method(Predicate<String> predicate) { 
        boolean veryLong = predicate.negate().test("HelloWorld"); 
        System.out.println("字符串很長嗎:" + veryLong); 
    }
    public static void main(String[] args) { 
        method(s ‐> s.length() < 5);
    }
}

練習:集合信息篩選

題目

數(shù)組當中有多條“姓名+性別”的信息如下,請通過 Predicate 接口的拼裝將符合要求的字符串篩選到集合

ArrayList 中,需要同時滿足兩個條件:

  • 必須為女生;
  • 姓名為4個字

代碼演示:

package com.itheima.demo01.Lambda;

import java.util.ArrayList;
import java.util.function.Predicate;

public class Demo06Test {
    public static void main(String[] args) {
        String [] arr={ "迪麗熱巴,女", "古力娜扎,女", "馬爾扎哈,男", "趙麗穎,女"};
       ArrayList<String> arry= method(arr,
                (t)->{
                    //切割字符串數(shù)組,判斷名字長度
                    String name = t.split(",")[0];
                   return name.length()==4;

                },
                (t)->{
                    //切割字符串數(shù)組,判斷性別
                    String sex = t.split(",")[1];
                    return sex.equals("女");
                });
        System.out.println(arry);
    }

    public static ArrayList<String> method(String[] arr, Predicate<String> p1, Predicate<String> p2) {
        //定義一個集合,存儲過濾之后的信息
        ArrayList<String> list = new ArrayList<>();
        //遍歷字符串數(shù)組
        for (String s : arr) {
            //使用and方法連接連個Predicate接口,比較
            boolean b = p1.and(p2).test(s);
            //對得到的布爾值進行判斷
            if (b){
                //條件成立,存儲信息
                list.add(s);
            }

        }
        return list;

    }
}

//結(jié)果:[迪麗熱巴,女, 古力娜扎,女]

Function接口

java.util.function.Function<T,R> 接口用來根據(jù)一個類型的數(shù)據(jù)得到另一個類型的數(shù)據(jù),前者稱為前置條件,

后者稱為后置條件。

抽象方法:apply

Function 接口中最主要的抽象方法為: R apply(T t) ,根據(jù)類型T的參數(shù)獲取類型R的結(jié)果。

使用的場景例如:將 String 類型轉(zhuǎn)換為 Integer 類型。

代碼演示:

import java.util.function.Function; 
public class Demo11FunctionApply {
    private static void method(Function<String, Integer> function) { 
        int num = function.apply("10");
        System.out.println(num + 20); 
    }
    public static void main(String[] args) { 
        method(s ‐> Integer.parseInt(s));
    }
}

默認方法:andThen

Function 接口中有一個默認的 andThen 方法,用來進行組合操作

需求:

  • 把string類型的"123",轉(zhuǎn)換為Inteter類型,把轉(zhuǎn)換后的結(jié)果加10
  • 把增加之后的Integer類型的數(shù)據(jù)。轉(zhuǎn)換為String類型

分析:

  • 轉(zhuǎn)換了兩次
  • 第一次是把string類型轉(zhuǎn)換為了Integer類型

所以我們可以使用Function<String, Integer> funI

Integer i - fuq1. apply(.“123”)+10;

第二次是把Integer類型轉(zhuǎn)換為string類型

所以我們可以使用Function<Integer. String> fun2

string s = fun2. opply(i);

我們可以使用andThen方法,把兩次轉(zhuǎn)換組合在一起使用

String S = fun1 pndThen(fun2). apply(“123”);
  • fun1先調(diào)用apply方法,把字符串轉(zhuǎn)換為Integer
  • fun2再調(diào)用apply方法,把Integer轉(zhuǎn)換為字符串

image-20210712185321379

練習:自定義函數(shù)模型拼接

題目

請使用 Function 進行函數(shù)模型的拼接,按照順序需要執(zhí)行的多個函數(shù)操作為:

String str = “趙麗穎,20”;
  • 將字符串截取數(shù)字年齡部分,得到字符串;
  • 將上一步的字符串轉(zhuǎn)換成為int類型的數(shù)字;
  • 將上一步的int數(shù)字累加100,得到結(jié)果int數(shù)字。

代碼演示:

package com.itheima.demo01.Lambda;

import java.util.function.Function;

public class Demo07Test {
    /**/
    public static void method(String s, Function<String,Integer> fun){
        Integer it = fun.apply(s);
        System.out.println(it+100);

    }

    public static void main(String[] args) {
        String str = "趙麗穎,20";
        String age = str.split(",")[1];
        method(age,
                (ss)->{
            return  Integer.parseInt(ss);

        });
    }
}

//120


總結(jié)

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

相關文章

  • JavaWeb開發(fā)實現(xiàn)備忘錄

    JavaWeb開發(fā)實現(xiàn)備忘錄

    這篇文章主要為大家詳細介紹了JavaWeb開發(fā)實現(xiàn)備忘錄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java流程控制語句最全匯總(中篇)

    Java流程控制語句最全匯總(中篇)

    這篇文章主要介紹了Java流程控制語句最全匯總(中篇),本文章內(nèi)容詳細,通過案例可以更好的理解數(shù)組的相關知識,本模塊分為了三部分,本次為中篇,需要的朋友可以參考下
    2023-01-01
  • Java基于API接口爬取商品數(shù)據(jù)的示例代碼

    Java基于API接口爬取商品數(shù)據(jù)的示例代碼

    Java作為一種流行的編程語言,可以用于編寫程序來調(diào)用這些API接口,從而獲取商品數(shù)據(jù),本文將介紹如何使用Java基于API接口爬取商品數(shù)據(jù),包括請求API、解析JSON數(shù)據(jù)、存儲數(shù)據(jù)等步驟,并提供相應的代碼示例,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • java中創(chuàng)建寫入文件的6種方式詳解與源碼實例

    java中創(chuàng)建寫入文件的6種方式詳解與源碼實例

    這篇文章主要介紹了java中創(chuàng)建寫入文件的6種方式詳解與源碼實例,Files.newBufferedWriter(Java 8),Files.write(Java 7 推薦),PrintWriter,File.createNewFile,FileOutputStream.write(byte[] b) 管道流,需要的朋友可以參考下
    2022-12-12
  • springboot實現(xiàn)全局異常處理及自定義異常類

    springboot實現(xiàn)全局異常處理及自定義異常類

    這篇文章主要介紹了springboot實現(xiàn)全局異常處理及自定義異常類,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • spring四種依賴注入方式的詳細介紹

    spring四種依賴注入方式的詳細介紹

    本篇文章主要介紹了spring四種依賴注入方式的詳細介紹,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java Spring開發(fā)環(huán)境搭建及簡單入門示例教程

    Java Spring開發(fā)環(huán)境搭建及簡單入門示例教程

    這篇文章主要介紹了Java Spring開發(fā)環(huán)境搭建及簡單入門示例,結(jié)合實例形式分析了spring環(huán)境搭建、配置、使用方法及相關注意事項,需要的朋友可以參考下
    2017-11-11
  • 一文詳解Spring構(gòu)造函數(shù)推斷

    一文詳解Spring構(gòu)造函數(shù)推斷

    這篇文章主要介紹了Spring構(gòu)造函數(shù)推斷自動注入及底層原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加
    2023-04-04
  • java構(gòu)造http請求的幾種方式(附源碼)

    java構(gòu)造http請求的幾種方式(附源碼)

    本文主要介紹了java構(gòu)造http請求的幾種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Spring TaskScheduler使用實例解析

    Spring TaskScheduler使用實例解析

    這篇文章主要介紹了Spring TaskScheduler使用實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11

最新評論