Java8函數式編程以及Lambda表達式

来源:https://www.cnblogs.com/yulinfeng/archive/2020/03/23/12552786.html
-Advertisement-
Play Games

第一章 認識Java8以及函數式編程 儘管距離Java8發佈已經過去7、8年的時間,但時至今日仍然有許多公司、項目停留在Java7甚至更早的版本。即使已經開始使用Java8的項目,大多數程式員也仍然採用“傳統”的編碼方式。 即使是在Java7就已經有了處理異常的新方式—— ,但大多數程式員也仍然採用 ...


第一章 認識Java8以及函數式編程

關註公眾號(CoderBuff)回覆“stream”獲取《Java8 Stream編碼實戰》PDF完整版。

《Java8 Stream編碼實戰》的代碼全部在https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/stream-coding,一定要配合源碼閱讀,並且不斷加以實踐,才能更好的掌握Stream。

儘管距離Java8發佈已經過去7、8年的時間,但時至今日仍然有許多公司、項目停留在Java7甚至更早的版本。即使已經開始使用Java8的項目,大多數程式員也仍然採用“傳統”的編碼方式。

即使是在Java7就已經有了處理異常的新方式——try-with-resources,但大多數程式員也仍然採用在finally語句中關閉相應的資源。

我認為Java8和Java5的意義同等重要,Java5的眾多新特性使得Java正式邁入編程界的統治地位。同樣,Java8的發佈,也使得這一門“古老”的語言具備了更加現代化的特性。

Java8最為引入矚目就是支持函數式編程

如果說面向對象編程是對數據的抽象,那麼函數式編程就是對行為的抽象[1]

button.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent event) {
            System.out.println("button clicked");
        }
});
以上示例來自於《Java 8函數式編程》

這個示例是為了一個按鈕增加一個監聽,當點擊這個按鈕時,將會觸發列印“button clicked”行為。

在Java支持函數式編程以前,我們如果需要傳遞一個行為常用的方式就是傳遞一個對象,而匿名內部類正是為了方便將代碼作為數據進行傳遞。

當然,函數式編程,並不是在Java8中才提出來的新概念,

函數式編程屬於編程範式中的一種,它起源於一個數學問題。我們並不需要過多的瞭解函數式編程的歷史,要追究它的歷史以及函數式編程,關於範疇論、柯里化早就讓人立馬放棄學習函數式編程了。

對於函數式編程我們所要知道的是,它能將一個行為傳遞作為參數進行傳遞。至於其他的,就留給學院派吧。

第二章 Lambda表達式

在第一章的示例中,我們看到在以前想要傳遞一個行為,我們通常使用的是匿名內部類,而從Java8開始,引入了一種全新更為簡潔的方式來支持函數式編程,那就是——Lambda表達式。

我們把第一章中的示例改為Lambda作為本章的開始。

button.addActionListener(event -> System.out.println("button clicked"));

Lambda表達式語法規則主體分為兩個部分,中間用“->”右箭頭連接,左邊代表參數,右邊代表函數主體。

2.1 函數式介面

在Java中有一個介面中只有一個方法表示某特定方法並反覆使用,例如Runnable介面中只有run方法就表示執行的線程任務。

Java8中對於這樣的介面有了一個特定的名稱——函數式介面。Java8中即使是支持函數式編程,也並沒有再標新立異另外一種語法表達。所以只要是只有一個方法的介面,都可以改寫成Lambda表達式。在Java8中新增了java.util.function用來支持Java的函數式編程,其中的介面均是只包含一個方法。

例如Predicate介面中只包含test方法,該函數介面接受一個輸入參數,返回一個布爾值。

函數式介面中的方法可以有參數、無參數、有返回值、無返回值。

  • () -> System.out.println("hellobug"),表示無參數。

  • event -> System.out.println("hellobug"),表示只有一個參數。

  • (x, y) -> {System.out.println(x); System.out.println(y);},表示兩個參數,可以不必指定參數類型,為了更清楚地表達意圖,最好還是加上參數類型,(String x, String y) -> {System.out.println(x); System.out.println(y);}

接下來我們來編寫一個帶參數且有返回的函數式介面

package com.coderbuff.chapter2_lambda.function;

/**
 * 函數式介面
 * @FunctionalInterface 註解只是為了表明這是一個函數式介面,函數式介面只能包含一個方法。
 * @author okevin
 * @date 2020/3/14 23:32
 */
@FunctionalInterface
public interface FunctionalInterfaceDemo {
    boolean test(Integer x);
}
com.coderbuff.chapter2_lambda.function.FunctionalInterfaceDemo

除了@FunctionalInterface註解,其它和一個普通的介面無任何差別。@FunctionalInterface註解只是為了標註這是一個函數式介面,如果標註了@FunctionalInterface註解,此時介面中就只能包含一個方法,因為函數式介面只能包含一個方法。

接著我們在測試類中編寫一個方法,方法的參數就是這個函數式介面,這代表了我們將傳遞行為

package com.coderbuff.chapter2_lambda.function;

/**
 * 按匿名類的方式使用一個函數式介面,傳遞行為
 * @author okevin
 * @date 2020/3/14 23:42
 */
public class AnonymousInnerClassTest {

    private void testAnonymousInnerClass(FunctionalInterfaceDemo functionalInterfaceDemo) {
        Integer number = 1;
        boolean result = functionalInterfaceDemo.test(number);
        System.out.println(result);
    }
}
com.coderbuff.chapter2_lambda.function.AnonymousInnerClassTest

testAnonymousInnerClass方法的含義表示將通過FunctionalInterfaceDemo#test方法判斷傳入的參數1返回布爾值。

我們應該如何通過Lambda表達式來使用這個函數式介面呢?

前面我們說了,這個參數代表了我們將傳遞一個行為,這個行為決定了1返回是true還是false,我們先通過匿名內部類實現這個介面。

package com.coderbuff.chapter2_lambda.function;

/**
 * 按匿名類的方式使用一個函數式介面,傳遞行為
 * @author okevin
 * @date 2020/3/14 23:42
 */
public class AnonymousInnerClassTest {

    private void testAnonymousInnerClass(FunctionalInterfaceDemo functionalInterfaceDemo) {
        Integer number = 1;
        boolean result = functionalInterfaceDemo.test(number);
        System.out.println(result);
    }

    public static void main(String[] args) {
        AnonymousInnerClassTest anonymousInnerClassTest = new AnonymousInnerClassTest();

        anonymousInnerClassTest.testAnonymousInnerClass(new FunctionalInterfaceDemo() {
            @Override
            public boolean test(Integer x) {
                if (x > 1) {
                    return true;
                }
                return false;
            }
        });
    }
}

這是在Java8之前通過匿名內部類實現行為的傳遞,在有了Lambda表達式後,通過上文的Lambda表達式語法規則,這是一個參數+一個返回(Lambda表達式中有返回值時return可以省略),並且有多行代碼。

anonymousInnerClassTest.testAnonymousInnerClass(number -> {
    if (number > 1) {
        return true;
    }
    return false;
});

關註公眾號(CoderBuff)回覆“stream”搶先獲取PDF完整版。

近期教程:

《ElasticSearch6.x實戰教程》

《Redis5.x入門教程》

《Java8 編碼實戰》

這是一個能給程式員加buff的公眾號 (CoderBuff)
  1. 《On Java 8》 ↩︎


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

-Advertisement-
Play Games
更多相關文章
  • SpringBoot AOP處理請求日誌處理列印 "趙小胖個人博客" ...
  • import導入的是包中的類(不包含包) 建議:不要寫通配符*,需要什麼導入什麼。 導入的類重名,必須加包名。 url完成包名定義。 ...
  • 轉載聲明 本系列文章轉自某技術大佬的博客https://www.cnblogs.com/bangerlee/ 該系列文章是我在網上能夠找到的最全面的分散式理論介紹文章了,一直沒看到有人整理這個系列文章,所以這次我就來做技術好文的搬運工,給整合了一把,覺得寫得好的朋友不妨去這位大佬的博客上打賞一把。 ...
  • Go中存在著不少內置函數,此類函數並不需要引入相關Package就可以直接使用該類函數。在Go的源碼builtin包的builtin.go中定義Go所有的內置函數;但該文件僅僅是定義描述出了所有內置函數,並不包含函數的任何實現代碼,該文件除了定義了內置函數還定義了部分內置類型; 內置函數使用 len ...
  • Java 7 為懶惰的Java開發人員帶來了一些非常好的功能。 嘗試資源 是這種功能之一,它可以減少代碼行,並使代碼更健壯。在本教程中,我將討論有關此功能的內容。 1. 資源清除的舊方法(在Java 7之前) 我們長期以來一直在這樣做。例如,從文件系統讀取文件。代碼可能看起來有所不同,但流程如下例所 ...
  • 承接上文 通過discovery和define完成了第一輪企業級別的發散和收斂。 即:站在企業的高度,基於企業願景和內外部環境,通過戰略分解和現狀調研,應用企業架構的方法確定了最終的平臺型企業架構,並確定了需要哪些中台,以及建設先後的問題。 中台的設計階段:進行第二輪的發散和收斂,站在一個中台產品的 ...
  • 在Java 7發行版中,oracle在異常處理機制上也做了一些不錯的更改。這些主要是 改進的catch塊 和 多餘的throws子句 。讓我們看看他們是如何改變的。 1.改進了Java 7中的catch塊 在此功能中,現在您可以 在單個catch塊中捕獲多個異常 。在Java 7之前,您只能在每個c ...
  • 入門訓練3 圓的面積 問題描述 給定圓的半徑r,求圓的面積。 輸入格式 輸入包含一個整數r,表示圓的半徑。 輸出格式 輸出一行,包含一個實數,四捨五入保留小數點後7位,表示圓的面積。 說明:在本題中,輸入是一個整數,但是輸出是一個實數。 對於實數輸出的問題,請一定看清楚實數輸出的要求,比如本題中要求 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...