arrays.stream()默认返回顺序流,需显式调用.parallel()才能转为并行流;适用于大数据量、计算密集型任务,操作须无状态且线程安全,小数据量反而降低性能。

Java中Arrays.stream()本身不直接生成并行流,但可通过.parallel()方法将普通流转为并行流,适用于对象数组的大数据处理。
理解Arrays.stream()的默认行为
Arrays.stream(T[] array)返回的是顺序流(sequential stream),不是并行流。即使数据量大,它也不会自动并行化。
- 调用
Arrays.stream(arr)→ 得到Stream<t></t>,默认是顺序执行 - 需显式调用
.parallel()才能启用多线程处理 - 并行流底层使用ForkJoinPool公共池,适合计算密集型任务
将对象数组转为并行流的正确写法
以Person[]为例:
Person[] people = {/* ... 大量Person对象 */};
Stream<person> parallelStream = Arrays.stream(people).parallel();
</person>
后续操作(如filter、map、reduce)将在多个线程中并发执行。
- 确保操作无状态、线程安全(避免修改共享可变状态)
- 避免在流中使用
System.out.println()等非线程安全I/O - 慎用
forEach,推荐用forEachOrdered保证顺序,或改用collect
并行流适用场景与注意事项
并非所有场景都适合并行流,尤其要注意开销和效果平衡:
- 数据量建议 ≥ 数万元素,小数组反而因线程调度开销更慢
- 操作应尽量无副作用、计算密集(如字符串解析、数值运算)
- 避免阻塞操作(如数据库查询、文件读写),会拖慢整个ForkJoinPool
- 可临时设置并行度:
ForkJoinPool.commonPool().setParallelism(4)(谨慎调整)
完整示例:统计对象属性并行聚合
对10万Person对象按年龄分组计数:
long count = Arrays.stream(people)
.parallel()
.filter(p -> p.getAge() >= 18)
.count(); // 并行执行,效率提升明显
<p>Map<integer long> ageCount = Arrays.stream(people)
.parallel()
.collect(Collectors.groupingByConcurrent(
Person::getAge,
Collectors.counting()
));
</integer></p>
groupingByConcurrent比普通groupingBy更适合并行流,内部使用线程安全的并发Map。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











