325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化

文章目录

  • [325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化](#325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化)
    • [✨ 什么是 Collector 的特性?](#✨ 什么是 Collector 的特性?)
    • [🔍 三种核心特性详解](#🔍 三种核心特性详解)
    • [🧪 示例讲解每个特性](#🧪 示例讲解每个特性)
      • [✅ `IDENTITY_FINISH`:无需转换,直接返回中间结果](#✅ IDENTITY_FINISH:无需转换,直接返回中间结果)
      • [🔁 `UNORDERED`:顺序无关,性能优先](#🔁 UNORDERED:顺序无关,性能优先)
      • [⚙️ `CONCURRENT`:支持并发累积,适合并行流](#⚙️ CONCURRENT:支持并发累积,适合并行流)
    • [🚦 特性组合示意](#🚦 特性组合示意)
    • [🎯 特性总结对照表](#🎯 特性总结对照表)
    • [📌 小贴士](#📌 小贴士)

325. Java Stream API - 理解 Collector 的三大特性:助力流处理优化

在 Java Stream API 中,自定义或使用收集器(Collector)时,我们可以通过定义 特性(Characteristics) 来告诉流引擎如何优化执行过程。理解这些特性,不仅有助于你写出更高效的 Collector,也能帮助你掌握流在并行或顺序执行中的行为。


✨ 什么是 Collector 的特性?

每个 Collector 都可以声明一些内部特性(characteristics) ,它们由 Collector.Characteristics 枚举类型定义。

这些特性由 Collector 接口中的 characteristics() 方法返回,返回类型为 Set<Collector.Characteristics>,用于指示该收集器的行为约定,进而帮助 Stream 更好地优化执行。


🔍 三种核心特性详解

特性名 描述 适用场景
IDENTITY_FINISH 表示中间容器本身就是最终结果,因此不需要调用 finisher() 方法。 如:toList() 内部用的是 ArrayList,返回的就是它本身
UNORDERED 表示不保证元素处理顺序 如:toSet() 不保证顺序
CONCURRENT 表示支持并发累加器,可在并行流中安全使用 如:使用线程安全结构如 ConcurrentHashMap

🧪 示例讲解每个特性

IDENTITY_FINISH:无需转换,直接返回中间结果

java 复制代码
Collector<String, List<String>, List<String>> toListCollector = new Collector<>() {
    public Supplier<List<String>> supplier() {
        return ArrayList::new;
    }

    public BiConsumer<List<String>, String> accumulator() {
        return List::add;
    }

    public BinaryOperator<List<String>> combiner() {
        return (list1, list2) -> {
            list1.addAll(list2);
            return list1;
        };
    }

    public Function<List<String>, List<String>> finisher() {
        return Function.identity(); // 不做任何转换
    }

    public Set<Characteristics> characteristics() {
        return Set.of(Characteristics.IDENTITY_FINISH);
    }
};

🧠 说明

因为 A(中间容器)和 R(最终结果)类型一致,finisher() 只是返回自己,因此可以声明 IDENTITY_FINISH,流引擎将跳过调用 finisher() 提升性能。


🔁 UNORDERED:顺序无关,性能优先

java 复制代码
Set<String> result = Stream.of("A", "B", "C", "A", "B")
    .collect(Collectors.toSet()); // Set 无序

🧠 说明
Collectors.toSet() 返回的收集器声明了 UNORDERED,意味着它不关心流中元素的顺序,甚至在并行时可能顺序完全打乱。这样可以减少排序或同步开销。


⚙️ CONCURRENT:支持并发累积,适合并行流

java 复制代码
Collector<String, ?, ConcurrentMap<Integer, List<String>>> concurrentCollector =
    Collectors.groupingByConcurrent(String::length);

ConcurrentMap<Integer, List<String>> map = List.of("one", "three", "four", "five", "six", "seven")
    .parallelStream() // 并行流
    .collect(concurrentCollector);

🧠 说明

该收集器声明了 CONCURRENT,表示其使用了线程安全的数据结构(如 ConcurrentMap),可以在并行流中安全使用,无需锁。


🚦 特性组合示意

java 复制代码
@Override
public Set<Characteristics> characteristics() {
    return Set.of(
        Characteristics.CONCURRENT,
        Characteristics.UNORDERED,
        Characteristics.IDENTITY_FINISH
    );
}

🧠 提示 :组合多个特性时,Stream API 会据此自动选择并行策略、是否执行 finisher、是否保证顺序等优化策略。


🎯 特性总结对照表

特性名 是否可省略 finisher 是否保证顺序 是否线程安全
IDENTITY_FINISH ✅ 是 🔶 不保证(视其他特性) 🔶 不保证
UNORDERED ❌ 否 ❌ 否 🔶 可能是
CONCURRENT ❌ 否 ❌ 否 ✅ 是

📌 小贴士

  • 如果你写的收集器返回的就是累加容器本身,记得加上 IDENTITY_FINISH
  • 想要并行处理但又安全?使用 CONCURRENT 并搭配线程安全结构。
  • 如果你对元素顺序无所谓,那就大胆用 UNORDERED 获取更多优化空间!
相关推荐
RFG20128 小时前
20、详解Dubbo框架:消费方如何动态获取服务提供方地址?【微服务架构入门】
java·人工智能·后端·微服务·云原生·架构·dubbo
光泽雨8 小时前
C# 中 Assembly 类详解
开发语言·c#
少控科技8 小时前
C#基础训练营 - 02 - 运算器
开发语言·c#
Riemann~~9 小时前
C语言嵌入式风格
c语言·开发语言
zjttsh9 小时前
Linux下安装Redis
java
TimberWill9 小时前
SpringBoot整合Srping Security实现权限控制
java·spring boot·后端
Renhao-Wan10 小时前
Java 算法实践(四):链表核心题型
java·数据结构·算法·链表
zmzb010311 小时前
C++课后习题训练记录Day104
开发语言·c++
zmzb010311 小时前
C++课后习题训练记录Day105
开发语言·c++·算法