Java Stream.reduce()方法操作實(shí)際案例講解
reduce
是Java Stream API中的一個(gè)核心操作,用于將流中的元素組合起來產(chǎn)生單個(gè)結(jié)果。它實(shí)現(xiàn)了"歸約"(也稱為"折疊")操作,是函數(shù)式編程中的重要概念。
一、reduce的基本概念
1. 什么是reduce操作
reduce操作將流中的元素反復(fù)結(jié)合起來,得到一個(gè)匯總結(jié)果。它可以實(shí)現(xiàn)求和、求積、找最大值/最小值、字符串連接等各種聚合操作。
2. reduce方法的三種形式
Java Stream API提供了三種reduce方法的重載形式:
最簡單的形式 - 只需要一個(gè)累加器函數(shù)
Optional<T> reduce(BinaryOperator<T> accumulator)
帶初始值的形式 - 提供一個(gè)初始值
T reduce(T identity, BinaryOperator<T> accumulator)
最通用的形式 - 包含合并器(combiner)用于并行流
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
二、reduce方法詳解
1. 基本形式:Optional<T> reduce(BinaryOperator<T> accumulator)
特點(diǎn):
- 返回Optional,因?yàn)榱骺赡転榭?/li>
- 需要處理Optional結(jié)果
示例:求最大值
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> max = numbers.stream() .reduce(Integer::max); max.ifPresent(System.out::println); // 輸出5
2. 帶初始值形式:T reduce(T identity, BinaryOperator<T> accumulator)
特點(diǎn):
- 提供初始值(identity)
- 流為空時(shí)返回初始值
- 不需要處理Optional
示例:求和
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, (a, b) -> a + b); System.out.println(sum); // 輸出15
3. 通用形式:<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
特點(diǎn):
- 支持類型轉(zhuǎn)換
- 第三個(gè)參數(shù)combiner用于并行流合并部分結(jié)果
- 最靈活但也最復(fù)雜
示例:拼接字符串
List<String> words = Arrays.asList("Hello", "World", "Java"); String combined = words.stream() .reduce("", (partial, element) -> partial + " " + element, String::concat); System.out.println(combined.trim()); // 輸出"Hello World Java"
三、reduce的底層原理
1. 順序流的reduce執(zhí)行過程
對于reduce(identity, accumulator)
:
- 初始化結(jié)果result = identity
- 對每個(gè)元素e,執(zhí)行result = accumulator.apply(result, e)
- 返回最終result
2. 并行流的reduce執(zhí)行過程
對于reduce(identity, accumulator, combiner)
:
- 流被分割為多個(gè)子流
- 每個(gè)子流獨(dú)立執(zhí)行reduce
- 使用combiner合并各個(gè)子流的結(jié)果
四、reduce的常見應(yīng)用場景
1. 數(shù)值計(jì)算
// 求和 int sum = numbers.stream().reduce(0, Integer::sum); // 求積 int product = numbers.stream().reduce(1, (a, b) -> a * b); // 求最大值 int max = numbers.stream().reduce(Integer.MIN_VALUE, Integer::max);
2. 字符串操作
// 字符串連接 String concat = strings.stream().reduce("", String::concat); // 拼接帶分隔符 String joined = strings.stream() .reduce((a, b) -> a + ", " + b) .orElse("");
3. 復(fù)雜對象歸約
// 計(jì)算員工總薪資 double totalSalary = employees.stream() .reduce(0.0, (sum, emp) -> sum + emp.getSalary(), Double::sum);
五、reduce的注意事項(xiàng)
1. 初始值(identity)的選擇
- 必須是累加器的恒等值,即
accumulator.apply(identity, x)
等于x
- 錯(cuò)誤的identity會(huì)導(dǎo)致錯(cuò)誤結(jié)果
2. 并行流中的combiner
- combiner必須滿足結(jié)合律:
combiner.apply(a, combiner.apply(b, c)) == combiner.apply(combiner.apply(a, b), c)
- 在順序流中combiner不會(huì)被使用
3. 性能考慮
- 對于簡單操作(如求和),專用方法(sum(), max()等)通常比reduce更高效
- 對于復(fù)雜歸約操作,reduce更靈活
六、reduce與collect的區(qū)別
特性 | reduce | collect |
---|---|---|
目的 | 將元素組合為單個(gè)值 | 將元素累積到可變?nèi)萜髦?/td> |
可變性 | 不可變操作 | 可變操作 |
并行性 | 需要滿足結(jié)合律 | 內(nèi)置支持并行 |
典型用途 | 數(shù)學(xué)運(yùn)算、簡單聚合 | 收集到集合、字符串拼接等 |
七、實(shí)際案例
案例1:統(tǒng)計(jì)訂單總金額
List<Order> orders = // 獲取訂單列表 BigDecimal total = orders.stream() .map(Order::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add);
案例2:合并多個(gè)Map
List<Map<String, Integer>> maps = // 多個(gè)map的列表 Map<String, Integer> result = maps.stream() .reduce(new HashMap<>(), (m1, m2) -> { m1.putAll(m2); return m1; });
八、總結(jié)
reduce
是Stream API中強(qiáng)大的聚合操作- 三種形式適應(yīng)不同場景,從簡單到復(fù)雜
- 理解identity和combiner的作用是關(guān)鍵
- 在并行流中要確保操作滿足結(jié)合律
- 對于簡單聚合,優(yōu)先考慮專用方法(sum, min, max等)
- 對于復(fù)雜歸約,reduce提供了最大的靈活性
掌握reduce操作可以讓你更高效地處理流數(shù)據(jù),實(shí)現(xiàn)各種復(fù)雜的聚合邏輯。
到此這篇關(guān)于Java Stream.reduce()方法深度解析的文章就介紹到這了,更多相關(guān)Java Stream.reduce()方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)點(diǎn)餐系統(tǒng)的登錄與退出功能流程詳解
結(jié)束了Springboot+MyBatisPlus也是開始了項(xiàng)目之旅,將從后端的角度出發(fā)來整理這個(gè)項(xiàng)目中重點(diǎn)業(yè)務(wù)功能的梳理與實(shí)現(xiàn)2022-10-10java 數(shù)據(jù)結(jié)構(gòu)單鏈表的實(shí)現(xiàn)
這篇文章主要介紹了java 數(shù)據(jù)結(jié)構(gòu)單鏈表的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-07-07基于SpringBoot實(shí)現(xiàn)HTTP請求簽名驗(yàn)證機(jī)制
在分布式系統(tǒng)交互中,API接口的安全性至關(guān)重要,本文將深入解析基于Spring Boot實(shí)現(xiàn)的HTTP請求簽名驗(yàn)證機(jī)制,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04java.lang.Runtime.exec的左膀右臂:流輸入和流讀取詳解
這篇文章主要介紹了java.lang.Runtime.exec的左膀右臂:流輸入和流讀取詳解,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot實(shí)現(xiàn)在webapp下直接訪問html,jsp
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)在webapp下直接訪問html,jsp問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10SpringBoot實(shí)現(xiàn)RabbitMQ三種使用方式
本文主要介紹了SpringBoot實(shí)現(xiàn)RabbitMQ三種使用方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07spring+hibernate 兩種整合方式配置文件的方法
本篇文章主要介紹了spring+hibernate 兩種整合方式配置文件的方法,主要有兩種方式 1、注解方式 2、xml方式實(shí)現(xiàn),有興趣的可以了解一下。2017-04-04Java實(shí)現(xiàn)“年-月-日 上午/下午時(shí):分:秒”的簡單代碼
當(dāng)前的日期輸出的方法有很多,本文為大家介紹下在java中是如何實(shí)現(xiàn)“年-月-日 上午/下午時(shí):分:秒”,感興趣的朋友不妨參考下2015-08-08