最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Stream 的 collect 與 reduce 操作示例詳解

 更新時(shí)間:2025年09月06日 09:50:43   作者:潛意識(shí)Java  
在 Java Stream API 中,collect?和?reduce?是兩種強(qiáng)大的終止操作,用于將流中的元素累積為最終結(jié)果,本文將從核心概念、使用場(chǎng)景、性能特性等多個(gè)維度進(jìn)行對(duì)比分析,感興趣的朋友跟隨小編一起看看吧

在 Java Stream API 中,collect 和 reduce 是兩種強(qiáng)大的終止操作,用于將流中的元素累積為最終結(jié)果。盡管它們都用于聚合數(shù)據(jù),但實(shí)現(xiàn)機(jī)制和應(yīng)用場(chǎng)景存在顯著差異。本文將從核心概念、使用場(chǎng)景、性能特性等多個(gè)維度進(jìn)行對(duì)比分析。

一、核心概念對(duì)比

特性collect(Collector)reduce(BinaryOperator)
操作類(lèi)型可變?nèi)萜鲄R聚操作不可變值累積操作
結(jié)果類(lèi)型可變?nèi)萜鳎ㄈ?List、Set、Map)單個(gè)值或容器(需通過(guò) Supplier 創(chuàng)建)
數(shù)據(jù)結(jié)構(gòu)支持中途修改的集合不可變對(duì)象的累積
并行處理效率高(可并發(fā)操作獨(dú)立容器后合并)低(需按順序累積或復(fù)雜 combiner)
典型應(yīng)用場(chǎng)景數(shù)據(jù)分組、分區(qū)、轉(zhuǎn)換集合類(lèi)型求和、求最大值、字符串拼接

二、collect 方法詳解

collect 是一種可變?nèi)萜鲄R聚操作,通過(guò) Collector 接口實(shí)現(xiàn)復(fù)雜的歸約邏輯。它將流中的元素累積到一個(gè)可變?nèi)萜鳎ㄈ?List、Set、Map)中,并支持進(jìn)一步的處理。

1. 基礎(chǔ)用法示例

// 將 Stream 轉(zhuǎn)換為 List
List<String> names = Stream.of("Alice", "Bob", "Charlie")
    .collect(Collectors.toList());
// 將 Stream 轉(zhuǎn)換為 Set 去重
Set<Integer> uniqueNumbers = Stream.of(1, 2, 2, 3, 3, 3)
    .collect(Collectors.toSet());
// 使用 toCollection 指定具體集合類(lèi)型
LinkedList<String> linkedList = Stream.of("a", "b", "c")
    .collect(Collectors.toCollection(LinkedList::new));

2. 高級(jí)用法:分組與分區(qū)

class Person {
    private String name;
    private int age;
    private String city;
    // 構(gòu)造器、getter 略
}
// 按城市分組
Map<String, List<Person>> peopleByCity = personStream
    .collect(Collectors.groupingBy(Person::getCity));
// 按年齡是否大于18分區(qū)
Map<Boolean, List<Person>> partitionByAge = personStream
    .collect(Collectors.partitioningBy(p -> p.getAge() > 18));

3. 自定義 Collector

// 自定義 Collector 實(shí)現(xiàn)字符串拼接
Collector<String, StringBuilder, String> stringCollector = Collector.of(
    StringBuilder::new,                  // 創(chuàng)建容器
    StringBuilder::append,               // 累積元素
    (sb1, sb2) -> sb1.append(sb2),       // 合并容器
    StringBuilder::toString              // 最終轉(zhuǎn)換
);
String result = Stream.of("Hello", " ", "World")
    .collect(stringCollector);  // 輸出:Hello World

三、reduce 方法詳解

reduce 是一種不可變值累積操作,通過(guò)二元操作(BinaryOperator)將流中的元素依次處理,最終得到一個(gè)值。

1. 基礎(chǔ)用法示例

// 無(wú)初始值的 reduce(返回 Optional)
Optional<Integer> sum = Stream.of(1, 2, 3, 4)
    .reduce(Integer::sum);  // 結(jié)果:10
// 有初始值的 reduce
int product = Stream.of(1, 2, 3, 4)
    .reduce(1, (a, b) -> a * b);  // 結(jié)果:24
// 復(fù)雜累積:字符串拼接
String concatenated = Stream.of("a", "b", "c")
    .reduce("", String::concat);  // 結(jié)果:abc

2. 并行流中的 reduce

// 并行流中使用帶 combiner 的 reduce
int sum = Stream.of(1, 2, 3, 4)
    .parallel()
    .reduce(0,  // 初始值
        Integer::sum,  // 累積器
        Integer::sum); // 合并器(并行流必須)

3. 自定義累積邏輯

// 計(jì)算最大值
Optional<Integer> max = Stream.of(5, 3, 9, 1)
    .reduce((a, b) -> a > b ? a : b);  // 結(jié)果:9
// 計(jì)算平均值(需要自定義累積器)
class Average {
    private int sum;
    private int count;
    public double get() {
        return count > 0 ? (double) sum / count : 0;
    }
}
Average average = Stream.of(1, 2, 3, 4, 5)
    .reduce(new Average(),
        (avg, num) -> {
            avg.sum += num;
            avg.count++;
            return avg;
        },
        (avg1, avg2) -> {
            avg1.sum += avg2.sum;
            avg1.count += avg2.count;
            return avg1;
        });
double result = average.get();  // 結(jié)果:3.0

四、核心區(qū)別與選擇策略

場(chǎng)景collect 更適合reduce 更適合
結(jié)果類(lèi)型集合或復(fù)雜對(duì)象單個(gè)值(如數(shù)字、字符串)
并行處理效率高(獨(dú)立容器可并發(fā)合并)低(需順序累積或復(fù)雜 combiner)
累積過(guò)程是否可變可變(操作集合內(nèi)部元素)不可變(生成新對(duì)象)
是否需要分組 / 分區(qū)是(groupingBy、partitioningBy)
是否需要多階段處理是(Collector 鏈)

五、性能對(duì)比與優(yōu)化建議

  • 并行流場(chǎng)景
    • collect:由于支持并發(fā)操作獨(dú)立容器后合并,性能通常優(yōu)于 reduce
    • reduce:若未正確實(shí)現(xiàn) combiner,可能導(dǎo)致并行效率低下
  • 大集合處理
    • collect:在分組、分區(qū)等復(fù)雜操作中表現(xiàn)更優(yōu)
    • reduce:在簡(jiǎn)單累積(如求和)中性能相當(dāng),但代碼可能更簡(jiǎn)潔
  • 內(nèi)存占用
    • collect:需要?jiǎng)?chuàng)建中間容器,內(nèi)存占用較高
    • reduce:僅維護(hù)累積值,內(nèi)存占用較低

六、實(shí)戰(zhàn)案例對(duì)比

1. 統(tǒng)計(jì)員工平均年齡

// 使用 collect
double averageAge = employees.stream()
    .collect(Collectors.averagingInt(Employee::getAge));
// 使用 reduce
OptionalDouble averageAge = employees.stream()
    .mapToInt(Employee::getAge)
    .average();

2. 按部門(mén)分組員工

// 使用 collect(推薦)
Map<String, List<Employee>> employeesByDepartment = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment));
// 使用 reduce(復(fù)雜且低效)
Map<String, List<Employee>> result = employees.stream()
    .reduce(
        new HashMap<>(),
        (map, emp) -> {
            map.computeIfAbsent(emp.getDepartment(), k -> new ArrayList<>())
               .add(emp);
            return map;
        },
        (m1, m2) -> {
            m2.forEach((dept, emps) -> 
                m1.computeIfAbsent(dept, k -> new ArrayList<>())
                  .addAll(emps));
            return m1;
        }
    );

3. 字符串拼接

// 使用 collect
String result = words.stream()
    .collect(Collectors.joining(", "));
// 使用 reduce
String result = words.stream()
    .reduce("", (s1, s2) -> s1.isEmpty() ? s2 : s1 + ", " + s2);

七、總結(jié)與最佳實(shí)踐

  • 優(yōu)先使用 collect
    • 當(dāng)需要生成集合、分組數(shù)據(jù)或執(zhí)行復(fù)雜轉(zhuǎn)換時(shí)
    • 在并行流場(chǎng)景中,collect 的性能通常更優(yōu)
  • 使用 reduce
    • 當(dāng)需要計(jì)算單個(gè)值(如求和、最大值)時(shí)
    • 當(dāng)累積過(guò)程不需要中間容器,且可以通過(guò)二元操作表達(dá)時(shí)
  • 復(fù)雜場(chǎng)景組合使用
// 先分組,再計(jì)算每組的平均值
Map<String, Double> avgScoreByClass = students.stream()
    .collect(Collectors.groupingBy(
        Student::getClassName,
        Collectors.averagingDouble(Student::getScore)
    ));
  • 避免過(guò)度使用 reduce
    • 對(duì)于復(fù)雜的集合操作,使用 reduce 可能導(dǎo)致代碼冗長(zhǎng)且難以維護(hù),應(yīng)優(yōu)先考慮 collect
    • 通過(guò)合理選擇 collect 和 reduce,可以使代碼更加簡(jiǎn)潔、高效,同時(shí)充分發(fā)揮 Stream API 的優(yōu)勢(shì)。

到此這篇關(guān)于Java Stream 的 collect 與 reduce 操作示例詳解的文章就介紹到這了,更多相關(guān)Java Stream 的 collect 與 reduce內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot如何使用@Cacheable進(jìn)行緩存與取值

    SpringBoot如何使用@Cacheable進(jìn)行緩存與取值

    這篇文章主要介紹了SpringBoot如何使用@Cacheable進(jìn)行緩存與取值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 解決mybatis case when 報(bào)錯(cuò)的問(wèn)題

    解決mybatis case when 報(bào)錯(cuò)的問(wèn)題

    這篇文章主要介紹了解決mybatis case when 報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過(guò)程

    mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過(guò)程

    這篇文章主要介紹了mybatis中使用InsertProvider注解報(bào)錯(cuò)解決全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • PropertiesLoaderUtils 出現(xiàn)中文亂碼的解決方式

    PropertiesLoaderUtils 出現(xiàn)中文亂碼的解決方式

    這篇文章主要介紹了PropertiesLoaderUtils 出現(xiàn)中文亂碼的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • SpringBoot @JsonDeserialize自定義Json序列化方式

    SpringBoot @JsonDeserialize自定義Json序列化方式

    這篇文章主要介紹了SpringBoot @JsonDeserialize自定義Json序列化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java有序二叉樹(shù)的刪除節(jié)點(diǎn)方式

    java有序二叉樹(shù)的刪除節(jié)點(diǎn)方式

    文章描述了在二叉樹(shù)中刪除節(jié)點(diǎn)的三種情況及其對(duì)應(yīng)的操作步驟,通過(guò)遞歸找到節(jié)點(diǎn)及其父節(jié)點(diǎn),并根據(jù)節(jié)點(diǎn)的子樹(shù)情況(無(wú)子樹(shù)、單子樹(shù)、雙子樹(shù))進(jìn)行相應(yīng)的刪除操作,文章還提供了一個(gè)測(cè)試類(lèi)來(lái)驗(yàn)證刪除操作的正確性
    2024-12-12
  • Java使用二分法進(jìn)行查找和排序的示例

    Java使用二分法進(jìn)行查找和排序的示例

    這篇文章主要介紹了Java使用二分法進(jìn)行查找和排序的示例,二分插入排序和二分查找是基礎(chǔ)的算法,需要的朋友可以參考下
    2016-04-04
  • 解決mybatis resultMap根據(jù)type找不到對(duì)應(yīng)的包問(wèn)題

    解決mybatis resultMap根據(jù)type找不到對(duì)應(yīng)的包問(wèn)題

    這篇文章主要介紹了解決mybatis resultMap根據(jù)type找不到對(duì)應(yīng)的包問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • idea代碼模板設(shè)置方式

    idea代碼模板設(shè)置方式

    這篇文章主要介紹了idea代碼模板設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java中關(guān)于String的全面解析

    Java中關(guān)于String的全面解析

    這篇文章主要介紹了Java中關(guān)于String全面解析,下面我們來(lái)一起學(xué)習(xí)一下吧
    2019-05-05

最新評(píng)論

鄂托克前旗| 开江县| 乾安县| 漳州市| 九龙城区| 南阳市| 云林县| 和林格尔县| 南安市| 桐庐县| 印江| 甘德县| 剑川县| 大邑县| 鄢陵县| 临汾市| 南阳市| 夏河县| 巧家县| 进贤县| 漾濞| 崇礼县| 桃源县| 房山区| 宁化县| 阳曲县| 庆云县| 蒙山县| 定日县| 昌平区| 富源县| 杭锦旗| 石家庄市| 济源市| 建始县| 五指山市| 开鲁县| 勐海县| 平塘县| 鹤岗市| 古丈县|