一文搞懂 Java8 reduce操作
來源:waynblog
什麼是 reduce
Java8 中有兩大最為重要的改變,其一是 Lambda 表示式,另一個就是 Stream API 了。
Stream 是 Java8 中處理集合的關鍵抽象概念,它將資料來源流化後,可以執行非常複雜的查詢、過濾和對映資料、排序、切片、聚合統計等操作。操作之後會產生一個新的流,而資料來源則不會發生改變。
在使用 Stream 操作的過程中,往往有三個步驟,
1. 建立 Stream
從一個資料來源(集合,陣列)中,新建一個 Stream 流。
2. 中間操作
一箇中間操作鏈,對 Stream 流的資料進行處理。比如查詢、過濾、對映轉換等。
3. 終止操作
一個終止操作,執行中間操作鏈,併產生結果。常用的終止操作有 forearch、collect、match、count、min、max、reduce
等。
其中本文主要講解的 reduct 操作就屬於是 Stream 流操作中的終止操作。
reduce 操作是一種通用的歸約操作,它可以實現從 Stream 中生成一個值,其生成的值不是隨意的,而是根據指定的計算模型。
比如終止操作中提到 count、min 和 max 方法,因為常用而被納入標準庫中。事實上這些方法都是一種 reduce 操作。
本文大綱如下,
reduce 操作三要素
為了方便大家理解 reduce (規約)操作,先給大家演示一下 reduce 操作的相關程式碼示例,
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result = numbers
.stream()
.reduce(0, (subtotal, element) -> subtotal + element);
assertThat(result).isEqualTo(21);
可以看到,我們的 reduce 操作接受了三個引數,返回了一個 int 基本型別。
在 Stream API 中,提供了三個 reduct 操作方法,根據引數不同進行區分。
對應上方程式碼示例,也就是使用了接受兩個引數的 reduce 方法,但其實接受兩個引數的 reduce 方法的程式碼邏輯是和接受三個引數的 reduce 方法是一致的。透過上方截圖可以看出。
所以這裡,我就直接給大家介紹下 reduce 操作的三個引數分別有什麼作用即可。
identiy 引數
identiy(初始值)是 reduce 操作的初始值,也就是當元素集合為空時的預設結果。對應上方程式碼示例,也就是說 reduce 操作的初始值是 0。
accumulator 引數
accumulator(累加器)是一個函式,它接受兩個引數,reduce 操作的部分元素和元素集合中的下一個元素。它返回一個新的部分元素。在這個例子中,累加器是一個 lambda 表示式,它將集合中兩個整數相加並返回一個整數:(a, b) -> a + b。
combiner 引數
combiner(組合器)是一個函式,它用於在 reduce 操作被並行化或者當累加器的引數型別和實現型別不匹配時,將 reduce 操作的部分結果進行組合。在上面程式碼示例中,我們不需要使用組合器,因為上面我們的 reduce 操作不需要並行,而且累加器的引數型別和實現型別都是 Integer。
為了方便大家理解 reduce 操作的內部邏輯,我給大家繪製了上面程式碼示例的執行示意圖,如下,
如何使用 reduce 操作
為了更好地理解初始值,累加器和組合器的功能,讓我們看一些基本的例子。
使用 reduce 查詢整數集合的最小值
// 建立一個整數集合
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// 找出集合中的最小值
Integer min = numbers.stream().reduce((integer, integer2) -> {
if (integer < integer2) {
return integer;
} else {
return integer2;
}
}).get();
// 輸出結果
System.out.println(min); // 1
在這個例子中,我們使用了一個引數的 reduce 操作,它接受一個累加器函式。累加器函式會返回集合兩個元素中,較小的元素。
最終我們就可以找出集合中最小值 1。
使用 reduce 操作拼接字串列表
我們可以對一個字串列表使用 reduce 操作,將它們拼接成一個單一的字串:
// 建立一個字串列表
List<String> letters = Arrays.asList ("a", "b", "c", "d", "e");
// 使用 reduce 操作拼接字串列表
String result = letters
.stream ()
.reduce ("", (partialString, element) -> partialString + element);
// 輸出結果
System.out.println (result); // abcde
在這個例子中,我們將初始值設為 "",累加器函式設為 (a, b) -> a + b,它表示將兩個字串拼接起來。
我們可以看到,reduce 操作將累加器函式反覆應用到列表中的每個元素上,得到最終的結果 abcde。
使用並行流計算整數列表的總和
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5,6);
// 使用並行流和 reduce() 方法計算整數列表的總和
int result = numbers.parallelStream()
.reduce(0, (a, b) -> a + b, Integer::sum);
// 輸出結果
System.out.println(result); // 21
在這個例子中,我們使用 parallelStream() 方法將列表轉換為並行流,再使用 reduce() 方法對整數列表進行 reduce 操作,並使用 Integer::sum 作為合併函式 combiner,將平行計算的結果合併。
使用並行流的好處能夠充分利用多核 CPU 的優勢,使用多執行緒加快對集合資料的處理速度。
不過並行流也不是任何時候都可以使用的,並行流執行過程中實際按照多執行緒執行,多執行緒程式設計有的問題,並行流都有。
比如多執行緒的執行緒安全,執行順序等問題,並行流都是有的。這一點需要大家注意。
最後聊兩句
本文介紹了 Java8 Stream 流中,reduce 操作的相關概念和接收引數,包含初始值,累加器和組合器,最後介紹了 reduce 操作如何使用,希望大家喜歡。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024923/viewspace-3001342/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一文搞懂Java8 Lambda表示式(附帶視訊教程)Java
- 一文搞懂佇列佇列
- 一文搞懂RESTful APIRESTAPI
- 一文搞懂Zookeeper原理
- 一文搞懂 DevOpsdev
- Flutter | 一文搞懂 BuildContextFlutterUIContext
- 一文搞懂 MySQL 日誌MySql
- JS的reduce使用及操作方式JS
- 一文搞懂 this、apply、call、bindAPP
- 一文帶你搞懂RPCRPC
- 一文搞懂直方圖均衡直方圖
- 一文搞懂Cookie,Session,Token,JWTCookieSessionJWT
- 一文搞懂動態規劃動態規劃
- 一文搞懂 Cookie,Session,Token,JWTCookieSessionJWT
- 一文搞懂 ARM 64 系列: PACISB
- 一文搞懂 ARM 64: AUTIBSP
- Java8 的流式操作Java
- [譯] 一文帶你玩轉 Java8 Stream 流,從此操作集合 So EasyJava
- 陣列的reduce操作+物件陣列的map操作陣列物件
- 一文搞懂 Prometheus 的直方圖Prometheus直方圖
- 一文搞懂Java隨機數生成Java隨機
- 一文搞懂Go語言的pluginGoPlugin
- 一文搞懂MySQL體系架構!!MySql架構
- Java 基礎 一文搞懂泛型Java泛型
- 一文搞懂 CountDownLatch 用法和原始碼!CountDownLatch原始碼
- 一文搞懂所有Java集合面試題Java面試題
- 一文搞懂得物前端監控前端
- 一文搞懂影片編解碼原理
- 瀏覽器渲染原理(一文搞懂)瀏覽器
- 一文搞懂js中的typeof用法JS
- 一文搞懂JavaScript陣列的特性JavaScript陣列
- 一文搞懂到底什麼是 AQSAQS
- 一文搞懂 CGI, FastCGI, WSGI, uWSGI, uwsgiAST
- 一文搞懂 ARM 64 系列: ADCS
- [轉帖]一文搞懂LSM-Tree
- 一文搞懂 ARM 64 系列: 一文搞懂 ARM 64 系列: 函式呼叫傳參與返回值函式
- 一文搞懂TCP與UDP的區別TCPUDP
- 一文搞懂指標採集利器 Telegraf指標