jkd8特性

收集器 -- java.util.stream.Collectors

Collectors是 Stream API 的核心工具类,提供了一系列静态工厂方法,用于将 Stream 流中的元素收集为集合(List/Set/Map)、值(求和 / 计数 / 最值)、字符串等,支持并行处理,且用法灵活。

  • 基础收集:转为集合(List/Set/Map/ 数组)
方法签名 功能描述 示例
toList() 收集为List(jdk8中默认为Arraylist,线程不安全 ) List list = stream.collect(Collectors.toList());
toSet() 收集为 Set(默认是 HashSet,去重且无序) Set set = stream.collect(Collectors.toSet());
toCollection(Supplier collectionFactory) 收集为自定义集合(如 LinkedList、TreeSet) LinkedList linkedList = stream.collect(Collectors.toCollection(LinkedList::new));TreeSet treeSet = stream.collect(Collectors.toCollection(TreeSet::new));
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 收集为 Map(key 由 keyMapper 生成,value 由 valueMapper 生成) 示例:将用户列表转为「用户 ID→用户名」的 MapMap<Long, String> userMap = users.stream().collect(Collectors.toMap(User::getId, User::getName));
toMap(..., BinaryOperator++mergeFunction)++ 重载:解决 key 冲突(如两个元素生成相同 key 时,用 mergeFunction 合并 value) 示例:key 冲突时取后者的值Map<Long, String> userMap = users.stream().collect(Collectors.toMap(User::getId, User::getName, (v1, v2) -> v2));
toMap(..., Supplier mapFactory) 重载:指定 Map 实现(如 LinkedHashMap 保留插入顺序) Map<Long, String> linkedMap = users.stream().collect(Collectors.toMap(User::getId, User::getName, (v1, v2) -> v2, LinkedHashMap::new));
toConcurrentMap(...) 收集为并发安全的 Map(ConcurrentHashMap),用法同 toMap ConcurrentMap<Long, String> concurrentMap = users.stream().collect(Collectors.toConcurrentMap(User::getId, User::getName));
toArray(IntFunction<A[]> generator) 收集为指定类型的数组 String[] arr = stream.collect(Collectors.toArray(String[]::new));
  • 聚合计算:求和/计数/最值/平均值
    用于对 Stream 中的数值型元素(或可转为数值的元素)进行统计计算,返回单个结果。
方法签名 功能描述 示例
counting() 统计元素个数(等价于 stream.count(),但可作为复合收集器的一部分) long count = stream.collect(Collectors.counting());
summingInt(ToIntFunction<? super T> mapper) 按 mapper 转为 int 后求和(同理:summingLong/summingDouble) 示例:计算所有用户年龄总和: int totalAge = users.stream().collect(Collectors.summingInt(User::getAge));
averagingInt(ToIntFunction<? super T> mapper) 按 mapper 转为 int 后求平均值(返回 double,同理:averagingLong/averagingDouble) double avgAge = users.stream().collect(Collectors.averagingInt(User::getAge));
summarizingInt(ToIntFunction<? super T> mapper) 一次性获取总和、平均值、最值、个数(返回 IntSummaryStatistics,同理:summarizingLong/summarizingDouble) 示例:获取年龄统计信息: IntSummaryStatistics stats = users.stream().collect(Collectors.summarizingInt(User::getAge));System.out.println("总和:" + stats.getSum() + ",平均值:" + stats.getAverage());
maxBy(Comparator<? super T> comparator) 按比较器获取最大值(返回 Optional,避免空指针) 示例:获取年龄最大的用户: Optional maxAgeUser = users.stream().collect(Collectors.maxBy(Comparator.comparingInt(User::getAge)));
minBy(Comparator<? super T> comparator) 按比较器获取最小值(返回 Optional) Optional minAgeUser = users.stream().collect(Collectors.minBy(Comparator.comparingInt(User::getAge)));
  • 分组与分区:按条件分类元素
    1、分组(groupingBy):按任意条件分组(多组):将Stream元素按指定维度分组,结果为Map<分组键, 分组后的元素集合>。
方法签名 功能描述 示例
groupingBy(Function<? super T,? extends K> classifier) 按 classifier 生成的键分组,默认值为 List 示例:按用户性别分组:Map<String, List> groupByGender = users.stream().collect(Collectors.groupingBy(User::getGender));
groupingBy(..., Supplier mapFactory) 重载:指定分组结果的 Map 实现(如 LinkedHashMap 保留分组顺序) Map<String, List> linkedGroup = users.stream().collect(Collectors.groupingBy(User::getGender, LinkedHashMap::new));需要 jdk16+
groupingBy(..., Collector<? super T,A,D> downstream) 重载:多级分组 / 分组后聚合(downstream 是分组后的二次收集器) 示例 2:按性别分组后,收集每组用户名(二级收集):Map<String, List> genderNames = users.stream().collect(Collectors.groupingBy(User::getGender, Collectors.mapping(User::getName, Collectors.toList())));
groupingByConcurrent(...) 并行分组(返回 ConcurrentMap,适合大规模并行流) ConcurrentMap<String, List> concurrentGroup = users.parallelStream().collect(Collectors.groupingByConcurrent(User::getGender));
复制代码
2、分区(partitioningBy):按布尔条件分组(两组:true/false):是 groupingBy 的特殊情况,分组键固定为 Boolean,结果仅含两个分组(满足条件 / 不满足条件)。
方法签名 功能描述 示例
partitioningBy(Predicate<? super T> predicate) 按 predicate 条件分区,默认值为 List 示例:将用户分为「成年人(≥18)」和「未成年人」:Map<Boolean, List> partitionByAdult = users.stream().collect(Collectors.partitioningBy(u -> u.getAge() >= 18));
partitioningBy(..., Collector<? super T,A,D> downstream) 重载:分区后二次收集 .示例:分区后统计每组人数Map<Boolean, Long> adultCount = users.stream().collect(Collectors.partitioningBy(u -> u.getAge() >= 18, Collectors.counting()));
  • 字符串拼接:joining
    专门用于将 Stream 中的字符串元素(或可转为字符串的元素)拼接为一个字符串,支持分隔符、前缀、后缀。
方法签名 功能描述 示例
joining() 直接拼接(无分隔符) String join = Stream.of("a", "b", "c").collect(Collectors.joining()); // 结果:"abc"
joining(CharSequence delimiter) 按分隔符拼接 String join = Stream.of("a", "b", "c").collect(Collectors.joining(",")); // 结果:"a,b,c"
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 按分隔符拼接,且添加前缀和后缀 String join = Stream.of("a", "b", "c").collect(Collectors.joining(",", "[", "]")); // 结果:"[a,b,c]"
  • 规约与收集:reducing
    reducing 是通用的聚合方法,支持自定义聚合逻辑(类似 Stream.reduce()),但可作为复合收集器(如分组后聚合)。
方法签名 功能描述 示例
reducing(T identity, BinaryOperator accumulator) 以 identity 为初始值,用 accumulator 聚合元素 示例:计算年龄总和(等价于 summingInt):int totalAge = users.stream().map(User::getAge).collect(Collectors.reducing(0, Integer::sum));
reducing(BinaryOperator accumulator) 无初始值,返回 Optional(避免空流报错) Optional totalAge = users.stream().map(User::getAge).collect(Collectors.reducing(Integer::sum));
reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator++accumulator)++ 先通过 mapper 转换元素,再聚合 示例:转换为年龄后求和:int totalAge = users.stream().collect(Collectors.reducing(0, User::getAge, Integer::sum));
  • 其他实用方法
方法签名 功能描述 示例
mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream) 先转换元素,再用下游收集器收集(常用于复合场景,如分组后转换) 示例:分组后收集用户名到 Set:Map<String, Set> genderNames = users.stream().collect(Collectors.groupingBy(User::getGender, Collectors.mapping(User::getName, Collectors.toSet())));
filtering(Predicate<? super T> predicate, Collector<? super T,A,R> downstream) 先过滤元素,再用下游收集器收集(Java 9+ 新增,Java 8 需手动先 filter() 示例:过滤成年人后收集为 List:List adults = users.stream().collect(Collectors.filtering(u -> u.getAge() >= 18, Collectors.toList()));
collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) 先通过下游收集器收集,再对结果执行 finisher 转换 示例:收集为 List 后转为不可变集合:List immutableList = stream.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

核心注意事项(Java 8 版本限制)

1、filtering 是 Java 9+ 方法:Java 8 中需先调用 stream.filter(...) 再收集,不能直接用 Collectors.filtering;

2、toList() 实现不固定:Java 8 中默认返回 ArrayList,但官方未明确约定,若需固定集合类型(如 LinkedList),建议用 toCollection(LinkedList::new);

3、toMap() 键冲突报错:若未指定 mergeFunction,当出现重复 key 时会抛出 IllegalStateException,必须显式处理冲突;

4、并行流支持:所有 Collectors 方法均支持并行流(parallelStream),无需额外处理线程安全(底层通过 Combiner 合并结果)。

相关推荐
编织幻境的妖2 小时前
Python代码性能优化工具与方法
开发语言·python·性能优化
Fcy6482 小时前
二叉搜索树(C++实现)
开发语言·数据结构·c++·二叉搜索树
程序员-周李斌2 小时前
ArrayBlockingQueue 源码解析
java·开发语言·后端·哈希算法·散列表
Tim_102 小时前
【C++入门】02、C++程序初识
开发语言·c++
lkbhua莱克瓦242 小时前
项目知识——Next.js App Router体系
开发语言·javascript·项目知识
Cricyta Sevina2 小时前
Java 语言多线程核心概念全解析
java·开发语言
缘三水3 小时前
【C语言】15.指针(5)
c语言·开发语言·指针·语法
爱吃大芒果3 小时前
从零开始学 Flutter:状态管理入门之 setState 与 Provider
开发语言·javascript·flutter