Java8-Lambda表達(dá)式基礎(chǔ)語法和內(nèi)置四大核心函數(shù)式接口

Lambda表達(dá)式

Lambda是一個(gè)匿名函數(shù),我們可以把Lambda表達(dá)式理解為是一段可以傳遞的代碼(將代碼像數(shù)據(jù)一樣進(jìn)行傳遞),其可以代替實(shí)現(xiàn)接口中的抽象方法時(shí)的書寫匿名內(nèi)部類的繁瑣代碼。

舉個(gè)栗子:

Java中有個(gè)Runnable接口,直接使用該接口,需要重寫實(shí)現(xiàn)其接口內(nèi)部中的抽象方法。如下:

Runnable run = new Runnable() {
    @Override
    public void run() {
        System.out.println("old run");
    }
};
run.run();

該代碼可以使用lambda表達(dá)式簡化為:

 Runnable run1 = () -> System.out.println("lambda run");
 run1.run();

1. 基礎(chǔ)語法

java8中引入了一個(gè)新的操作符 ->,該操作符稱為箭頭操作符Lambda操作符,該箭頭符號將整個(gè)Lambda表達(dá)式拆分成兩部分:

左側(cè):Lambda表達(dá)式的參數(shù)列表,即接口中對應(yīng)抽象方法的參數(shù)列表

右側(cè):Lambda表達(dá)式中所需要執(zhí)行的功能,即Lambda表達(dá)式體。即需要實(shí)現(xiàn)的抽象方法功能體。

1.1. 語法格式一 無參數(shù),無返回值

對應(yīng)格式為: () -> 方法體... 括號內(nèi)無參數(shù)

例如:() -> Sysout...

@Test
public void test1 (){
    //無參數(shù) , 無返回值 對應(yīng)格式為: () -> 方法體...   括號內(nèi)無參數(shù)
    Runnable run = new Runnable() {
        @Override
        public void run() {
            System.out.println("old run");
        }
    };
    run.run();
    System.out.println("-----------");
    Runnable run1 = () -> System.out.println("lambda run");
    run1.run();
}
/*result:
    old run
    -----------
    lambda run
*/

1.2. 語法格式二 有一個(gè)參數(shù),無返回值

對應(yīng)語法格式為 (x) -> 無返回值的方法體

例如: (x) -> System.out.println(x)

有且只有一個(gè)參數(shù)左側(cè)的小括號可以省略不寫

例如: x -> System.out.println(x)

// 有一個(gè)參數(shù) , 無返回值
@Test
public void test2(){
    List<String> list = new ArrayList<>();
    Consumer<String> consumer = (s) -> list.add(s);//將consumer接收到的對象進(jìn)行具體的功能的消費(fèi)
    consumer.accept("ddd");
    consumer.accept("aaa");
    consumer.accept("ccc");
    list.forEach(System.out::println);
    /*
        Result:
            ddd
            aaa
            ccc
     */
}

1.3. 語法格式三 有兩個(gè)或兩個(gè)以上參數(shù),有返回值

兩個(gè)或兩個(gè)以上參數(shù),有返回值,并且 lambda 體中有多條語句

語法為: 
(x,y) -> {
    方法體
    return 返回值
}

多條語句必須使用大括號包括在內(nèi),
有返回值,需要使用return 返回返回值.
 Comparator<Integer> com = (x, y) -> {
    System.out.println("x為"+x);
    System.out.println("y為"+y);
    return Integer.compare(x,y);
    };


如果lambda體中只有一條語句,
那么大括號{}可以省略,
return關(guān)鍵字也可以省略

例如: 
Comparator<Integer> com = (x,y) -> {
    return Integer.compare(x,y);
}

就可以簡寫成:

Comparator<Integer> com = (x,y) -> Integer.compare(x,y);

 Lambda表達(dá)式的參數(shù)列表的 數(shù)據(jù)類型可以省略不寫,
因?yàn)镴VM編譯器可以通過上下文推斷出數(shù)據(jù)類型,即'類型推斷'.

即: 
(Integer x,Integer y) -> Integer.compare(x,y);

簡化成:
(x,y) -> Integer.compare(x,y);


@Test
public void test3(){
    Comparator<Integer> com = (x, y) -> {
        System.out.println("x為"+x);
        System.out.println("y為"+y);
        return Integer.compare(x,y);
    };
    System.out.println(com.compare(1111,111));
    // x為1111
    // y為111
    // 1
}

利用用Java內(nèi)置的Comparator接口(比較器)比較兩個(gè)字符串的長度,可用lambda表達(dá)式表示為:

使用Lambda表達(dá)式直接進(jìn)行該接口的核心方法體的重寫

//使用Lambda表達(dá)式直接進(jìn)行該接口的核心方法體的重寫
Comparator<String> com1 = (x,y) ->  {
    if(x.length() == y.length()){
        return 0;
    }else{
        if(x.length() > y.length()){
            return 1;
        }else
            return -1;

    }
};

System.out.println(com1.compare("aa","aaaaa"));// -1

2. 函數(shù)式接口

  • Lambda表達(dá)式需要函數(shù)式接口的支持

  • 函數(shù)式接口定義: 接口中只有一個(gè)抽象方法的接口,稱為函數(shù)式接口。

  • 可以使用注解 @FuncitonalInterface 修飾,其修飾作用為:限定該接口必須為函數(shù)式接口,即該接口中有且只有一個(gè)抽象方法。否則無法通過編譯。即可以檢查是否為函數(shù)式接口。

2.1. 自定義一個(gè)函數(shù)式接口:

@FunctionalInterface
public interface Operation<T,R> {
    public R operation(T t1, T t2);
}

2.1.1 方案一:寫具體實(shí)現(xiàn)方法再直接使用
public void op (Long l1, Long l2, Operation<Long,Long> operation){
        System.out.println(operation.operation(l1,l2));
    }
@Test
public void testMyOperation(){
    op(10l,10l,(x,y) -> x*y);//100
    op(100l,200l,(x,y)-> x+y);//300
}

2.1.2 方案二: 先使用lambda表示具體實(shí)現(xiàn)方法體,再進(jìn)行接口中的方法調(diào)用,傳入具體值:
@Test
public void testMyOperation(){
    Operation<Integer,Integer>  op = (x,y) -> x*y;
    System.out.println(op.operation(10,10));  //100
}

實(shí)際使用時(shí),大多數(shù)情況下直接使用Java8內(nèi)置四大函數(shù)式接口,并不要進(jìn)行自己寫函數(shù)式接口。


3. Java內(nèi)置的四大核心函數(shù)式接口

Consumer<T>  消費(fèi)型接口 消費(fèi)對象
    void accept(T t);
Supplier<T>  供給型接口 生成對象
    T get();
Function<R,T>  函數(shù)型接口 指定特定功能
    R apply(T t);
Predicate<T>  斷言型接口 進(jìn)行條件判斷
    boolean test(T t); 

3.1. 消費(fèi)型接口

Consumer<T> 消費(fèi)型接口
void accept(T t);

// Consumer<T> 消費(fèi)型接口
    @Test
    public void testConsumer(){
        //此時(shí)的(d) 小括號里有參數(shù) 
        //原因是因?yàn)?Consumer接口有參數(shù) 
        //void accept(T t);
        
        consume(1000,(d)-> System.out.println(d));
    }
    public void consume(Integer n , Consumer<Integer> con){
        //函數(shù)接口接收 消費(fèi) 形參n
        con.accept(n);
    }

3.2. 供給型接口

Supplier<T> 供給型接口

T get();小括號無參數(shù)

 // Supplier<T>  供給型接口
    @Test
    public void testSupplier(){
        //T get(); 小括號無參數(shù)
       List<Integer> numList = getNumList(10,() -> (int)(Math.random()*101));
        for ( Integer i: numList
             ) {
            System.out.println(i);
        }

    }
    //調(diào)用此方法時(shí),第二個(gè)參數(shù)提供一個(gè)數(shù)字集合
    public List<Integer> getNumList(int n, Supplier<Integer> sup){
        List<Integer> numList = new ArrayList<>();

        for (int i = 0; i < n; i++){
            numList.add(sup.get()); //通過get方法得到數(shù)字 存到numList
        }
        return numList;
    }

3.3. 函數(shù)型接口

Function<R,T> 函數(shù)型接口 指定特定功能

   //Function<R,T>  函數(shù)型接口 特定功能
    @Test
    public void testFunction(){
        //將字符串轉(zhuǎn)成大寫
        String str1 = strHandler("ghslkajh", (s) -> s.toUpperCase());
        System.out.println(str1);
    }

    // Function<R,T> 函數(shù)型接口
    //定義一個(gè)處理字符串功能型接口函數(shù)
    public  String strHandler(String str, Function<String,String> fun){
        return fun.apply(str);
    }

3.4. 斷言型接口

Predicate<T> 條件判斷

boolean test(T t); 返回boolean

 //斷言型接口  Predicate<T>
    // boolean test(T t);  返回boolean
    @Test
    public void testPredicate(){
        //返回長度大于3的字符串
        List<String> s1 = strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.length() > 3);
        System.out.println(s1); //[huzhiqi, adaad, 1231, 414441, gagsgasg]
        //返回包含d的字符串
        List<String> s2 = strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.contains("d"));
        System.out.println(s2); // [adaad]
    }
    //使用斷言型接口過濾字符串
    public List<String> strFilter(List<String> strs, Predicate<String> pred){
        List<String>  list = new ArrayList<>();
        for (String s:strs
             ) {
            //利用斷言型接口進(jìn)行指定功能判斷  即一個(gè)功能性條件判斷
            if(pred.test(s)){
                //過濾功能
                list.add(s);
            }
        }
        return list;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容