Java8 Consumer、Supplier、Predicate、Function

来源:https://www.cnblogs.com/toutou/p/java_Function_Consumer.html
-Advertisement-
Play Games

今天我們還講講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) 
  1. 這個方法返回一個組合的Consumer,先執行當前Consumer操作,然後再執行afterConsumer操作。
  2. 如果在此操作或操作之後有異常,則將其中繼到當前組合操作。
  3. 如果這個操作出現異常,那麼後面的操作將不會被執行。

例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);

其他參考/學習資料:

v源碼地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn


作  者:請叫我頭頭哥
出  處:http://www.cnblogs.com/toutou/
關於作者:專註於基礎平臺的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 多線程在訪問同一個共用變數時很可能會出現併發問題,特別是在多線程對共用變數進入寫入時,那麼除了加鎖還有其他方法避免併發問題嗎?本文將詳細講解 ThreadLocal 的使用及其源碼。 ...
  • 根據不同場景使用不同方案進行實現尤為必要。通常開發過程中,文件較小,直接將文件轉化為位元組流上傳到伺服器,但是文件較大時,用普通的方法上傳,顯然效果不是很好,當文件上傳一半中斷再次上傳時,發現需要重新開始,這種體驗不是很爽,下麵介紹幾種好一點兒的上傳方式。 這裡講講如何在Spring bo... ...
  • Stirling-PDF —— 一個基於 Web 的 PDF 操作工具,支持對 PDF 文件進行各種操作,包括分割、合併、轉換、重組、添加圖像、旋轉、壓縮等。 ...
  • 1 開源解析和拆分文檔 第三方工具去對文件解析拆分,將文件內容給提取出來,並將我們的文檔內容去拆分成一個小的chunk。常見的PDF word mark down, JSON、HTML。都可以有很好的一些模塊去把這些文件去進行一個東西去提取。 1.1 優勢 支持豐富的文檔類型 每種文檔多樣化選擇 與 ...
  • 正文 21 日正是周五,夏至。全年當中,白天時長最長的一天。而恰好那天也是銀行扣息的日子。所以很忙,我差點沒能走掉。 所幸最終還是有驚無險。 到斯的家裡,是晚上 9 點鐘。比我想得要早。這個周周四,他過生日。但是那天因為上班,所以移到了周末。不是法定節假日,很普通的一個周末。全年有很多個這樣的周末。 ...
  • 大模型在一定程度上去改變了我們生活生工作的思考的方式,然後也越來越多的個人還有企業在思考如何將大模型去應用到更加實際的呃生產生活中去,希望大語言模型能夠呃有一些更多企業級別生產落地的實踐,然後去幫助我們解決一些業務上的問題。目前 1 LLM的問題 1.1 幻覺 LLM因為是一個預訓練模型,它已有一些 ...
  • SingleStringMathTex是Mobjects分類中用來顯示數學公式的class。manim中有3個可以用來顯示數學公式的class,還有兩個是MathTex和Tex,後續再介紹。 從SingleStringMathTex的名稱中也可以看出,它是用來顯示只有一行的簡單公式。SingleSt ...
  • 1 模型 來看兩種不同類型的模型--LLM 和聊天模型。然後,它將介紹如何使用提示模板來格式化這些模型的輸入,以及如何使用輸出解析器來處理輸出。 LangChain 中的語言模型有兩種類型: 1.1 Chat Models 聊天模型通常由 LLM 支持,但專門針對會話進行了調整。提供者 API 使用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...