java8的介面
① java8介面有defaultmethod後是不是可以放棄抽象類了
Java 8引入default method旨在讓已有介面適應新功能,無需實現類更改。以List介面為例,在Java SE 7時,其未包含sort()方法。Java SE 8時添加此方法,已實現List介面的類無需重新編譯即可利用新增功能。默認方法允許介面提供默認實現,使得實現類無需實現介面新增方法即可使用。
默認方法的設計初衷是為了配合Java的函數式編程風格,使介面更靈活地接受FunctionalInterface參數,優化代碼結構。
盡管Java 8的介面提供了default method,但它們暫時無法完全取代抽象類。抽象類能包含狀態信息,而介面只能提供公有虛方法的默認實現。Java 9介面引入非公有靜態方法,未來版本可能進一步增強功能,提供更多替代抽象類的可能。
舉例說明,ActionListener介面在Java中常要求實現者提供空實現。引入default method後,介面能為所有方法提供默認實現,簡化代碼編寫過程,避免實現類自行編寫大量空實現的繁瑣工作,更符合函數式編程的簡潔風格。
② Java8精華-函數式編程-Consumer(二)
在上篇文章中,我們探討了如何將匿名內部類轉換為 Lambda 表達式,這是一個基礎且關鍵的技能。本文將深入 Java 8 中的函數式編程概念,聚焦於幾個核心功能介面,並通過具體實例展示它們的用法與特性。隨著 Java 8 的引入,多個函數式介面被添加到語言中,這些介面在處理數據時發揮著重要作用,尤其是與集合類如 List、Set、Map 等的結合。
首先,讓我們了解 Java 8 中引入的函數式介面的作用。它們被設計用於簡化集合操作,提供了一種更為靈活且緊湊的方式來處理數據。通過引入@FunctionalInterface 註解,Java 強化了函數式編程的特性,確保介面僅包含一個抽象方法,這使得它們成為 Lambda 表達式的完美載體。
盡管@FunctionalInterface 註解不是必須的,但強烈推薦使用它,因為它有助於提高代碼的可讀性,明確指出一個介面是為函數式編程設計的。這種註解的存在不僅限於新引入的介面,一些舊的類如 Runnable、Callable 等,即便沒有被標注,只要它們只包含一個抽象方法,同樣被視為函數式介面。
接下來,我們將詳細介紹幾個核心功能介面,特別是 Consumer 介面。Consumer 是最為常用的介面之一,其主要功能是在不返回任何結果的情況下處理單個元素。這個介面是處理集合元素的首選,尤其是在使用forEach 方法時。forEach 方法接受 Consumer 作為參數,這意味著在遍歷集合時,你可以輕松地將 Lambda 表達式作為參數傳遞,以實現特定的處理邏輯。
Consumer 介面的核心是它的抽象方法 accept(T t),用於接收並處理單個元素。這個介面還提供了一個名為 andThen() 的默認方法,允許你將一個 Consumer 與另一個 Consumer 鏈接起來,形成一個復合的 Lambda 表達式。這使得處理多個操作變得簡單且高效,例如,你可以先計算一個元素的平方,然後再計算它的立方。
實現 Consumer 介面的方式有兩種:使用匿名內部類或 Lambda 表達式。Lambda 表達式的使用簡化了代碼,使其更加簡潔且易於理解。在某些情況下,你甚至可以直接忽略數據類型,因為編譯器會推斷它。在處理多個操作或需要連接多個 Consumer 對象時,將 Lambda 表達式分配給變數並將其傳遞給 forEach 方法,可以提供更大的靈活性。
讓我們通過實例來探索 Consumer 介面的和Then() 方法。這個方法允許你連接兩個 Consumer 對象,執行一系列操作。例如,你可以先計算元素的平方,然後計算立方。這種鏈式調用使得代碼更加優雅且易於維護。
在最後的總結中,我們強調了@FunctionalInterface 註解的重要作用以及它在 Java 8 中如何強化了函數式編程的概念。通過學習這些核心功能介面及其使用方法,你將能夠更高效地處理數據,實現更加靈活且簡潔的代碼結構。在接下來的文章中,我們將繼續探索 Java 8 中的其他功能介面,如 BiConsumer,帶你進一步深入函數式編程的世界。
③ Java8 parallelStream淺析
在Java8中,lamda表達式和Stream介面的引入顯著簡化了代碼,增強了表達能力,同時也提高了效率。Stream介面中的parallelStream方法提供並發操作的支持,本文將深入探討parallelStream的使用方法。
讓我們先來看看Java文檔對parallelStream的定義。parallelStream允許並行執行操作,簡化了多線程編程。
接下來,我們通過一個例子來直觀感受stream和parallelStream的區別。從執行結果中,我們可以看到stream順序輸出,而parallelStream的輸出順序無序,且parallelStream的執行時間僅為stream的五分之一。這表明在當前測試場景下,parallelStream在性能上表現出色。
parallelStream的性能提升得益於ForkJoin框架和ForkJoinPool的使用。ForkJoin框架是Java7中提供的並行執行框架,其策略為分而治之,即將任務分解為多個子任務並行執行,然後合並結果。
ForkJoin框架與ThreadPoolExecutor的區別在於,ForkJoin框架可以高效處理大量任務,且支持父子依賴關系,而ThreadPoolExecutor則無法支持這種場景。
Java 8在ForkJoinPool中添加了一個通用線程池,用於處理自動並行化任務。這個線程池能夠自動並行化數組排序、元素遍歷等操作。在並行計算邏輯方面,使用ForkJoinPool相較於ThreadPoolExecutor更具有優勢,尤其是在代碼可讀性和代碼量上。
默認的線程數量等於計算機處理器數量,用戶可以通過系統屬性調整此數量:-Djava.util.concurrent.ForkJoinPool.common.parallelism={N}。
我們對代碼進行了調整,將sleep時間改為2ms。執行結果顯示,doParallelStream耗時最多,這表明並不是所有情況下並行執行都能帶來最佳性能。具體場景需通過測試和分析來確定。
並發操作中,線程安全問題不容忽視。一個示例展示了stream.parallel.forEach()中的操作可能不具有線程安全性。解決此問題,可以將集合轉換為同步集合,例如:Collections.synchronizedList(new ArrayList<>())。
總結,parallelStream提供了並行執行的強大能力,但用戶需根據實際應用場景評估性能,同時注意線程安全問題。