昨天介紹了 Lambda 表達式, 廣泛地說只要介面只有一個抽象方法就可以使用 Lambda 表達式,而 在 Java 標準程式庫裡面,有個套件專門用來存放會被程式庫其他部分重複使用的泛函介面,這個套件稱為java.util.function,套件有四個介面定義:
java.util.function.Consumer 介面包含了兩個方法
void accept(T t)
以下是一個簡單的範例,把字串串列 println 出來
Part 1:內部匿名類別的實作
這裡是 java.util.Iterable 的 default 方法(List 繼承自 Iterable,也接收了 forEach 方法) forEach 接受了 Consumer 引數
Part 2:Lambda 表達式
Part 3:方法參考
//Part 1
List<String> strings = Arrays.asList("this", "is", "a", "list", "of", "strings");
strings.forEach(new Consumer<String>(){
@Override
public void accept(String s){
System.out.println(s);
}
});
//Part 2
strings.forEach(s -> System.out.println(s));
//Part 3
strings.forEach(System.out::println);
java.util.function.Consumer 介面抽象方法如下,不接受任何引數產生一個物件:
T get()
以下是一個簡單的例子,使用 log 輸出一個隨機數
Part 1:內部匿名類別的實作
Part 2:Lambda 表達式
Part 3:方法參考
// Part 1
DoubleSupplier randomSupplier = new DoubleSupplier() {
@Override
public double getAsDouble() {
return Math.random();
}
};
//Part 2
randomSupplier = () -> Math.random();
randomSupplier = Math::random;
// deferred execution
Logger logger = Logger.getLogger(this.getClass().getName());
logger.debug(randomSupplier);
logger.debug(Math.random()); // must execution
使用 Supplier 一個主要用途是支援延遲執行(deferred execution),的概念,如果 T get() 這個 T 物件的建立成本很高,不透過 supplier 產生物件可能就是 new 一個出來使用,再根據場景作要不要使用的處理,著名的例子是 logger 在上例裡面如果 log level 設定為 info 則 randomSupplier 裡面的Math.random(); 並不會執行,同樣如果我們使用 logger.debug(Math.random()); 則 Math.random() 一定會被執行
java.util.function.Predicate 介面抽象方法如下,主要的目的是篩選串流:
boolean test(T t)
以下是一個簡單的例子,印出比 5 大的數字:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> collect = list.stream()
.filter(x -> x > 5).collect(Collectors.toList());
System.out.println(collect);
java.util.function.Function 介面抽象方法如下,主要的目的是將輸入參數轉成輸出值:
R apply(T t)
以下是一個簡單的例子,map 利用 Function 將 String 串列轉換成 Stream,最後再轉成List:
Part 1:內部匿名類別的實作
Part 2:Lambda 表達式
Part 3:方法參考
List<String> names = Arrays.asList("Mal", "Wash", "Kaylee", "Inara",
"Zoë", "Jayne", "Simon", "River", "Shepherd Book");
//Part 1
List<Integer> nameLengths =
names.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
})
.collect(Collectors.toList());
//Part 2
nameLengths = names.stream()
.map(s -> s.length())
.collect(Collectors.toList());
// Part 3
nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
現代Java:輕鬆解決Java 8 與 9 的難題 - 歐萊禮 2018
https://www.geeksforgeeks.org/java-8-predicate-with-examples/?ref=lbp