1. 程式人生 > 其它 >Java 基礎(Lambda表示式 和 函式式 Functional 介面)

Java 基礎(Lambda表示式 和 函式式 Functional 介面)

Lambda表示式

函式式 Functional 介面

  1. 只包含一個抽象方法的介面,稱為函式式介面。
  2. 你可以通過 Lambda 表示式來建立該介面的物件。(若 Lambda 表示式丟擲一個受檢異常(即:非執行時異常),那麼該異常需要在目標介面的抽象方法上進行宣告)。
  3. 我們可以在一個介面上使用 @FunctionalInterface 註解,這樣做可以檢查它是否是一個函式式介面。同時 javadoc 也會包含一條宣告,說明這個介面是一個函式式介面。
  4. 在 java.util.function 包下定義了Java 8的豐富的函式式介面
  5. Java 從誕生日起就是一直倡導 “一切皆物件”,在Java裡面面向物件(OOP)程式設計是一切。但是隨著python、scala等語言的興起和新技術的挑戰,Java不得不做出調整以便支援更加廣泛的技術要求,也即 java 不但可以支援OOP還可以支援OOF(面向函式程式設計)
  6. 在函數語言程式設計語言當中,函式被當做一等公民對待。在將函式作為一等公民的程式語言中,Lambda表示式的型別是函式。但是在Java8中,有所不同。在Java8中,Lambda表示式是物件,而不是函式,它們必須依附於一類特別的物件型別——函式式介面。
  7. 簡單的說,在Java8中,Lambda表示式就是一個函式式介面的例項。這就是Lambda表示式和函式式介面的關係。也就是說,只要一個物件是函式式介面的例項,那麼該物件就可以用Lambda表示式來表示。
  8. 所以以前用匿名實現類表示的現在都可以用Lambda表示式來寫。

Java 內建四大核心函式式介面

其他介面

LambdaTest.java

package
com.klvchen.java1; import org.junit.Test; import java.util.Comparator; public class LambdaTest { @Test public void test1(){ Runnable r1 = new Runnable() { @Override public void run() { System.out.println("我愛北京天安門"); } }; r1.run(); System.out.println(
"**********************************"); Runnable r2 = () -> System.out.println("我愛北京故宮"); r2.run(); } @Test public void test2(){ Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1, o2); } }; int compare1 = com1.compare(12, 21); System.out.println(compare1); System.out.println("***************************************"); Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1,o2); int compare2 = com2.compare(32, 21); System.out.println(compare2); System.out.println("***************************************"); //方法引用 Comparator<Integer> com3 = Integer :: compare; int compare3 = com3.compare(32, 21); System.out.println(compare3); } }

LambdaTest1.java

package com.klvchen.java1;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

/*
   Lambda表示式的使用
   1.舉例: (o1,o2) -> Integer.compare(o1,o2);

   2.格式:
         ->左邊: Lambda形參列表的引數型別可以省略(型別推斷);如果Lambda形參列表只有一個引數,其一對()也可以省略
         ->右邊: Lambda體應該使用一對{}包裹;如果Lambda體只有一條執行語句(可能是return語句),可以省略這一對{}和return關鍵字

   3.Lambda 表示式的使用:(分為6種情況)

   4.Lambda 表示式的本質:作為介面的例項

   5.如果一個介面中,只聲明瞭一個抽象方法,則此介面就稱為函式式介面

   6.所以以前用匿名實現類表示的現在都可以用Lambda表示式來寫。

 */
public class LambdaTest1 {
    // 語法格式一:無參,無返回值
    @Test
    public void test1(){
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我愛北京天安門");
            }
        };

        r1.run();

        System.out.println("*****************************");

        Runnable r2 = () -> System.out.println("我愛北京故宮");

        r2.run();
    }

    //語法格式二:Lambda需要一個引數,但是沒有返回值。
    @Test
    public void test2(){
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };

        con.accept("謊言和誓言的區別是什麼?");

        System.out.println("*****************************");

        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };

        con1.accept("一個是聽得人當真了,一個是說的人當真了");
    }

    //語法格式三:資料型別可以省略,因為可由編譯器推斷得出,稱為"型別推斷"
    @Test
    public void test3(){
        Consumer<String> con1 = (String s) -> {
          System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");

        System.out.println("*****************************");

        Consumer<String> con2 = (s) ->{
            System.out.println(s);
        };

        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }

    @Test
    public void test4(){
        ArrayList<String> list = new ArrayList<>();//型別推斷

        int[] arr = {1, 2, 3};//型別推斷
    }

    //語法格式四: Lambda若只需要一個引數時,引數的小括號可以省略
    public void test5(){
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");

        System.out.println("*****************************");

        Consumer<String> con2 = s -> {
            System.out.println(s);
        };

        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }

    //語法格式五:Lambda需要兩個或以上的引數,多條執行語句,並且可以有返回值
    @Test
    public void test6(){
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };

        System.out.println(com1.compare(12,21));

        System.out.println("*****************************");
        Comparator<Integer> com2 = (o1,o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

        System.out.println(com2.compare(12,6));
    }

    //語法格式六:當Lambda體只有一條語句時,return 與大括號若有,都可以省略
    @Test
    public void test7(){
        Comparator<Integer> com1 = (o1, o2) -> {
            return o1.compareTo(o2);
        };

        System.out.println(com1.compare(12, 6));

        System.out.println("******************************************************");

        Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);

        System.out.println(com2.compare(12, 21));

    }

    @Test
    public void test8(){
        Consumer<String> con1 = s -> {
            System.out.println(s);
        };

        con1.accept("一個是聽得人當真了,一個是說的人當真了");

        System.out.println("******************************************************");

        Consumer<String> con2 = s -> System.out.println(s);

        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }



}

LambdaTest2.java

package com.klvchen.java1;

/*
  java內建的4大核心函最式介面
  消費型介面  Consumer<T>    void accept(T t)
  供給型介面  Supplier<T>    T get()
  函式型介面  Function<T,R>  R apply(T t)
  斷定型介面  Predicate<T>   booLean test(T t)
 */

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class LambdaTest2 {

    @Test
    public  void test1(){
        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("學習太累了,去天上人間買了瓶礦泉水,價格為: " + aDouble);
            }
        });

        System.out.println("**************************************************");

        happyTime(400, money -> System.out.println("學習太累了,去天上人間買了瓶礦泉水,價格為: " + money));

    }

    public void happyTime(double money, Consumer<Double> con) {
        con.accept(money);
    }


    @Test
    public void test2(){
        List<String> list = Arrays.asList("北京","南京","天津","東京","西京","普京");

        List<String> filterStrs = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });

        System.out.println(filterStrs);

        List<String> filterStrs1 = filterString(list, s -> s.contains("京"));

        System.out.println(filterStrs1);
    }

    //據給定的規剩,過濾集合中的字串。此規則由Predicate的方法決定
    public List<String> filterString(List<String> list, Predicate<String> pre){

        ArrayList<String> filterList = new ArrayList<>();

        for (String s : list) {
            if (pre.test(s)){
                filterList.add(s);
            }
        }

        return filterList;
    }
}