Collectors.partitioningBy()用于布尔二分,返回true/false键的Map;groupingBy()按分类函数分多组;切片应避免subList()陷阱,需深拷贝防并发问题。
用 Collectors.partitioningBy() 做二分:条件成立 / 不成立
这是最常用也最轻量的分割方式,适用于「非此即彼」的布尔判断。它返回一个 Map>,true 键对应满足条件的元素,false 键对应不满足的。
- 必须传入一个
Predicate,比如x -> x > 10或String::isEmpty - 底层是单次遍历,性能好;但只能分两组,不能扩展为三组或更多
- 注意空集合不会报错,但若流本身为
null,会抛NullPointerException - 示例:
List nums = Arrays.asList(1, 12, 5, 18, 3); Map<Boolean, List> parts = nums.stream() .collect(Collectors.partitioningBy(x -> x > 10));结果中
parts.get(true)是[12, 18]
用 Collectors.groupingBy() 按分类函数分组
当你需要按某个属性、计算结果或枚举值把集合拆成多组(不限于两个),就该用这个。它返回 Map>,键由你提供的分类函数决定。
- 分类函数返回值将作为分组键,所以要注意其
equals()和hashCode()行为(比如用自定义对象作键需重写) - 默认分组值是
ArrayList,如需控制顺序或类型,可额外传入下游收集器,例如groupingBy(keyFn, LinkedHashMap::new, toList()) - 如果分类函数返回
null,会触发NullPointerException(除非用Collectors.groupingByConcurrent()并配合Function.identity()等容错设计) - 示例:
Map<String, List> byDept = people.stream() .collect(Collectors.groupingBy(p -> p.getDepartment().getName()));
手动实现多条件切片:避免 subList() 的陷阱
有人误以为「分割」就是按索引切片(比如每 10 个一组),但这和条件分割本质不同。若真要按数量分块,别直接用 list.subList() 循环——它返回的是原列表的视图,修改子列表会影响原列表,且并发下不安全。