今天我們還講講Consumer、Supplier、Predicate、Function這幾個介面的用法,在 Java8 的用法當中,這幾個介面雖然沒有明目張膽的使用,但是,卻是潤物細無聲的。為什麼這麼說呢?這幾個介面都在 java.util.function 包下的,分別是Consumer(消費型) ...
今天我們還講講Consumer、Supplier、Predicate、Function這幾個介面的用法,在 Java8 的用法當中,這幾個介面雖然沒有明目張膽的使用,但是,卻是潤物細無聲的。為什麼這麼說呢?這幾個介面都在 java.util.function 包下的,分別是Consumer(消費型)、supplier(供給型)、predicate(謂詞型)、function(功能性),相信有了後面的解釋,你應該非常清楚這個介面的功能了。那麼,下麵,我們從具體的應用場景來講講這個介面的用法!
vConsumer
Java Consumer介面來自Java 8中引入的 java.util.function包。
Consumer是一個功能介面,用來作為lambda表達式或方法引用的任務目標(傳遞一個參數執行指定的方法)。
Consumer的功能介面是一個接受單一參數並且不返回任何結果的操作。
Consumer的功能方法是accept(T t)。
Consumer具有以下方法。
1. accept : 這是Consumer功能介面的功能方法。accept 方法對給定的參數進行這一操作。
2. andThen : 此方法返回一個組合的Consumer,該Consumer先執行原始的Consumer操作,然後按照從左到右的順序執行給定的andThen操作。
功能方法:accept
功能方法accept
在功能介面Consumer
中的定義
void accept(T t)
使用示例
ConsumerAccept.java
import java.util.function.Consumer; public class ConsumerAccept { public static void main(String[] args) { Consumer<String> nameConsumer = s -> System.out.println(s); nameConsumer.accept("Mahesh"); nameConsumer.accept("Krishna"); } }
輸出
Mahesh
Krishna
使用Lambda表達式創建Consumer
可以使用lambda表達式創建Consumer。
例1 基礎類型操作
在我們的示例中,我們將使用lambda表達式在此處創建兩個Consumer。
一個用於將數字添加到列表的方法,如果數字為奇數,則將添加到具有奇數的列表中;如果數字為偶數,則將其添加到具有偶數的另一個列表中。
ConsumerLambda1.java
import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class ConsumerLambda1 { public static void main(String[] args) { List<Integer> oddList = new ArrayList<>(); List<Integer> evenList = new ArrayList<>(); Consumer<Integer> storeNumber = n -> { if (n % 2 == 0) { evenList.add(n); } else { oddList.add(n); } }; Consumer<List<Integer>> printList = list -> list.forEach(n -> System.out.println(n)); storeNumber.accept(10); storeNumber.accept(15); storeNumber.accept(25); storeNumber.accept(30); System.out.println("--- Odd number ---"); printList.accept(oddList); System.out.println("--- Even number ---"); printList.accept(evenList); } }
輸出結果
--- Odd number --- 15 25 --- Even number --- 10 30
例2 對象類型操作
我們將使用lambda
表達式創建一個Consumer
,它將決定並顯示一個公民在選舉中是否可以投票的數據。
ConsumerLambda2.java
import java.util.function.Consumer; public class ConsumerLambda2 { public static void main(String[] args) { Consumer<Citizen> electionConsumer = c -> { if (c.getAge() < 18) { System.out.println(c.getName() + " is not eligible to vote."); } else { System.out.println(c.getName() + " can vote."); } }; electionConsumer.accept(new Citizen("Ritesh", 15)); electionConsumer.accept(new Citizen("Shreya", 20)); } } class Citizen { private String name; private int age; public Citizen(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
輸出結果
Ritesh is not eligible to vote.
Shreya can vote.
使用方法引用創建Consumer
Consumer可以使用方法引用來創建。
在我們的例子中,我們有一個有兩個方法的實用類Utility,其中一個方法將替換Map中的值,第二個方法顯示Map中的數據。我們將使用方法引用來創建Consumer。
ConsumerMethodRef.java
import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; public class ConsumerMethodRef { public static void main(String[] args) { Map<Integer, String> persons = new HashMap<Integer, String>(); persons.put(101, "Mahesh"); persons.put(102, "Krishna"); Consumer<Map<Integer, String>> updatePersons = Utility::updateData; Consumer<Map<Integer, String>> displayPersons = Utility::displayData; updatePersons.accept(persons); displayPersons.accept(persons); } } class Utility { static void updateData(Map<Integer, String> persons) { persons.replaceAll((k, v) -> "Shree ".concat(v)); } static void displayData(Map<Integer, String> persons) { for (Map.Entry<Integer, String> entry : persons.entrySet()) { System.out.println(entry.getKey() + " - " + entry.getValue()); } } }
輸出結果
101 - Shree Mahesh
102 - Shree Krishna
使用andThen方法
在Java
文檔中andThen
方法聲明。
default Consumer<T> andThen(Consumer<? super T> after)
- 這個方法返回一個組合的
Consumer
,先執行當前Consumer
操作,然後再執行after
的Consumer
操作。 - 如果在此操作或操作之後有異常,則將其中繼到當前組合操作。
- 如果這個操作出現異常,那麼後面的操作將不會被執行。
例1 簡單拼接Consumer
我們的示例中有兩個Consumer
。
首先將執行squareConsumer
,然後將執行printConsumer
。
ConsumerAndThen1.java
import java.util.Arrays; import java.util.List; import java.util.function.Consumer; public class ConsumerAndThen1 { public static void main(String[] args) { List<Integer> numList = Arrays.asList(3, 4, 5, 6); Consumer<List<Integer>> squareConsumer = list -> { for (int i = 0; i < list.size(); i++) { list.set(i, list.get(i) * list.get(i)); } }; Consumer<List<Integer>> printConsumer = list -> list.forEach(n -> System.out.println(n)); squareConsumer.andThen(printConsumer).accept(numList); } }
輸出
9 16 25 36
例2 多個拼接Consumer
我們多次使用andThen
。首先將執行oddNumConsumer
,然後將執行evenNumConsumer
,然後將執行taskFinishConsumer
。
ConsumerAndThen2.java
import java.util.Arrays; import java.util.List; import java.util.function.Consumer; public class ConsumerAndThen2 { public static void main(String[] args) { List<Integer> list = Arrays.asList(12, 13, 14, 15, 16, 17); Consumer<List<Integer>> oddNumConsumer = MyNumber::printOddNum; Consumer<List<Integer>> evenNumConsumer = MyNumber::printEvenNum; Consumer<List<Integer>> taskFinishConsumer = MyNumber::taskFinishMsg; oddNumConsumer.andThen(evenNumConsumer).andThen(taskFinishConsumer).accept(list); } } class MyNumber { static void printOddNum(List<Integer> myNumbers) { System.out.println("--- odd numbers ---"); myNumbers.forEach(n -> { if (n % 2 == 1) { System.out.print(n + " "); } }); } static void printEvenNum(List<Integer> myNumbers) { System.out.println("\n--- even numbers ---"); myNumbers.forEach(n -> { if (n % 2 == 0) { System.out.print(n + " "); } }); } static void taskFinishMsg(List<Integer> myNumbers) { System.out.println("\nTotal " + myNumbers.size() + " number processed."); } }
輸出結果
--- odd numbers ---
13 15 17
--- even numbers ---
12 14 16
Total 6 number processed.
vSupplier
Java 8引入了函數式介面 Supplier 是一個無參數的函數式介面,它不接受任何輸入參數,但可以返回一個結果。它定義了一個名為 get() 的抽象方法,用於獲取結果。
下麵是Supplier<T>介面的定義:
@FunctionalInterface public interface Supplier<T> { T get(); }
在函數式編程中, Supplier 介面常用於延遲計算或惰性求值。它可以用來表示一個供應商或提供者,用於生成或獲取數據。當需要獲取數據時,可以調用 Supplier 的 get() 方法來獲取結果。使用 Supplier 介面的主要優勢之一是它可以與Java 8的新特性lambda表達式結合使用。通過lambda表達式,可以以更簡潔和易讀的方式定義 Supplier 對象。
下麵是一個使用Supplier介面的示例:
import java.util.function.Supplier; public class SupplierExample { public static void main(String[] args) { // 使用lambda表達式創建Supplier對象 Supplier<String> supplier = () -> "你好,世界!"; String result = supplier.get(); // 調用get()方法獲取結果 System.out.println(result); } } // 輸出:你好,世界!
在上面的示例中,我們使用lambda表達式創建了一個返回字元串"Hello, World!"的 Supplier 對象。然後,我們調用了 get() 方法來獲取結果,並將其列印到控制臺上。
除了簡單的返回固定值之外, Supplier 介面還可以用於生成隨機數、讀取文件、從資料庫中獲取數據等各種場景。通過實現 Supplier 介面的自定義類,我們可以根據具體需求來生成或獲取數據。
以下是其他常見用法示例:
1. 提供隨機數生成器:
Supplier<Integer> randomGenerator = () -> new Random().nextInt(); int randomNumber = randomGenerator.get();
2. 延遲載入資源:
Supplier<DatabaseConnection> connectionSupplier = () -> new DatabaseConnection(); DatabaseConnection connection = connectionSupplier.get();
3. 惰性初始化對象:
Supplier<ExpensiveObject> lazyInitializer = ExpensiveObject::new; ExpensiveObject object = lazyInitializer.get();
總結一下,Java 8的函數式介面 Supplier 用於表示一個供應商或提供者,它不接受任何輸入參數,但可以返回一個結果。它可以與lambda表達式結合使用,用於延遲計算或惰性求值。
vPredicate
Java 8中引入了Predicate功能介面。Java Predicate表示一個參數的謂詞。Predicate是一個布爾值的函數。Java Predicate是一個功能介面,屬於java.util.function包。Predicate的功能方法是test(T t)。Predicate的其他方法是isEqual、and、or、negate和not。not方法在Java 11中被引入。
Predicate<Integer> predicate = new Predicate<Integer>() { @Override public boolean test(Integer integer) { if(integer > 5){ return true; }else{ return false; } } }; System.out.println(predicate.test(6)); // true Predicate<Integer> predicate2 = (t) -> t > 5; System.out.println(predicate2.test(1)); // false Predicate<String> isUserNameValid = u -> u != null && u.length() > 5 && u.length() < 10; System.out.println(isUserNameValid.test("Mahesh")); // true
vFunction
函數式介面(Functional Interface)就是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的介面。且用@Function標簽標記的介面。Java8 新增加的函數介面在 java.util.function 包下,它包含了很多類,用來支持 Java 的函數式編程。
Function< T , R >函數產生給定數據類型的結果,並接受一個參數作為給定數據類型,T參數類型,R是結果類型。Function 介面是一個功能型介面,它的一個作用就是轉換作用,將輸入數據轉換成另一種形式的輸出數據。
Function<Integer,String> ob = f1 -> "Age:"+f1; System.out.println(ob.apply(20)); // 輸出:Age:20
Function<String, Integer> function = new Function<String, Integer>() { @Override public Integer apply(String s) { return s.length();//獲取每個字元串的長度,並且返回 } }; Stream<String> stream = Stream.of("qqq", "wwwww", "eeeeee"); Stream<Integer> stream1 = stream.map(function); stream1.forEach(System.out::println);
其他參考/學習資料:
- https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/Consumer.html
- https://www.concretepage.com/java/java-8/java-consumer
- https://blog.csdn.net/qq_31635851/article/details/116207886
v源碼地址
https://github.com/toutouge/javademosecond/tree/master/hellolearn
作 者:請叫我頭頭哥
出 處:http://www.cnblogs.com/toutou/
關於作者:專註於基礎平臺的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!