Java | Lambda表示式

weixin_34116110發表於2018-09-30

Lamba的有效寫法

接收一個 String型 引數,並返回一個 int,隱式的返回一個 int

(String s) -> s.length();

接收一個 Apple 型別引數,返回一個 boolean 型

(Apple a) -> a.getWeight() > 150

多個引數,沒有返回值,可以包含多條語句

(int x, int y) -> {
    System.out.println("Result: ");
    System.out.println(x + y);
}

沒有引數返回 int

() -> 42

語句需要花括號括起來,表示式可以省略花括號。


我們可以在函式式介面上使用Lambda表示式,所謂函式式介面,就是隻定義了一個抽象方法的介面(Object 的public方法除外)。比如 Runnable 介面

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

@FunctionalInterface 註解表示你接下來要宣告介面是函式介面,如果你用了該註解,而介面卻不符合函式式介面的規範,那麼編譯器將會返回一個錯誤。

Lambda實踐環繞執行 與 行為引數化實現步驟

下面是從一個檔案中讀取一行所需要的模板程式碼(使用了帶資源的try語句,會自動關閉資源)

    public static String processFile(BufferedReaderProcessor p) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader("C:\\data.txt"))) {
            return p.process(br);
        }
    }

上面就是環繞執行的例子,處理一個資源,常見的模式就是,開啟一個資源,做一些處理,然後關閉資源。這個開啟很清理階段總是很類是,並且圍繞著 執行處理的中要程式碼,這就是環繞執行。


1902085-3c57ac21b7a11c43.png
環繞執行

我們可以通過將 處理程式碼引數化,來簡化程式碼。

用 Lambda 來實現實現行為引數化,大致分四個步驟

第一步

首先建立函式式介面,用以傳遞行為

@FunctionalInterface
public interface BufferedReaderProcessor {
    
    String process(BufferedReader b) throws IOException;
}
第二步

將函式式介面作為框架方法的引數

    public static String processFile(BufferedReaderProcessor p) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\wqj24\\Desktop\\bbs.sql"))) {
            return p.process(br);  // 通過函式式介面傳遞的行為
        }
    }
第三步

通過傳遞不同的 Lambda 表示式,重用processFile方法,用不同的方式處理檔案

String oneLine = processFile(br -> br.readLine());  // 讀取一行
String twoLine = processFile(br -> br.readLine() + br.readLine());  // 讀取兩行
// ...

Java 8 中核心函式式介面

Predicate

斷言型,接收一個泛型 T 物件,並返回一個 boolean,你可以在需要表示涉及型別 T 的布林表示式時,使用該介面作為引數,然後傳遞行為程式碼。

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}
Consumer

消費型,接收泛型 T 物件,沒有返回值(void),如果你需要訪問物件T物件,並對其執行某些操作,就可以使用這個介面

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);
}
Function

函式型,java.util.function.Function<T, R> 介面定義了一個 apply 的方法,它接收一個 T 物件,返回一個 泛型R物件,如果你需要將輸入物件對映到輸出,可以使用這個介面

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
}
Supplier

供給型,定義了一個 get 方法,無引數,返回一個泛型 T 物件,如果你需要獲取物件,可以使用這個介面。

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

相關文章