对于stream的效率问题,来做一下测试:
自定义类型:
@Data
public class StreamEntity {
private Long id;
private String name;
private Integer value;
}
测试类:
public class StreamTest {
@Test
public void streamEfficiency(){
List<Integer> integerList = new ArrayList<>();
List<StreamEntity> streamList = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 30000; ++i){
Integer number = random.nextInt(30000);
integerList.add(number);
StreamEntity streamEntity = new StreamEntity();
streamEntity.setId(Long.valueOf(number));
streamEntity.setName(String.valueOf(i));
streamEntity.setValue(number);
streamList.add(streamEntity);
}
// 简单集合
long preTime1 = System.currentTimeMillis();
Integer result = integerList.get(0);
for (int j = 0; j < integerList.size(); ++j){
int tmp = integerList.get(j);
if (tmp > result){
result = tmp;
}
}
System.out.println("简单集合普通for循环计算耗时:" + (System.currentTimeMillis() - preTime1) + " 结果:"+ result);
long preTime2 = System.currentTimeMillis();
int result2 = integerList.stream().mapToInt(v -> v).max().getAsInt();
System.out.println("简单集合单线程stream计算耗时:" + (System.currentTimeMillis() - preTime2)+ " 结果:" + result2);
long preTime3 = System.currentTimeMillis();
int result3 = integerList.parallelStream().mapToInt(v -> v).max().getAsInt();
System.out.println("简单集合多线程并行stream计算耗时:" + (System.currentTimeMillis() - preTime3)+ " 结果:" + result3);
Integer result4 = streamList.get(0).getValue();
long preTime4 = System.currentTimeMillis();
for (int k = 0; k < streamList.size(); ++k){
StreamEntity tmp = streamList.get(k);
if (tmp.getValue() > result4){
result4 = tmp.getValue();
}
}
// 自定义集合
System.out.println("自定义集合普通for循环计算耗时:" + (System.currentTimeMillis() - preTime4)+ " 结果:" + result4);
long preTime5 = System.currentTimeMillis();
int result5 = streamList.stream().mapToInt(v -> v.getValue()).max().getAsInt();
System.out.println("自定义集合单线程stream计算耗时:" + (System.currentTimeMillis() - preTime5)+ " 结果:" + result5);
long preTime6 = System.currentTimeMillis();
int result6 = streamList.parallelStream().mapToInt(v -> v.getValue()).max().getAsInt();
System.out.println("自定义集合多线程stream计算耗时:" + (System.currentTimeMillis() - preTime6)+ " 结果:" + result6);
}
}
运行结果(个人电脑配置可能会影响运行结果请多次试验):
因此个人觉得 关于stream的效率问题要有分类的对比说明。
关于以上的对比结果简单总结:
对于简单操作,比如最简单的遍历求最大值,Stream串行API性能明显差于普通for循环,但并行的Stream API能够发挥多核特性。
对于复杂操作,Stream串行API性能可以和普通遍历相差不大,在并行执行时Stream 效果优于其他另个。(注:并行流的内部使用了默认的 ForkJoinPool(java1.7添加) 分支/合并框架,它的默认线程数量就是你的处理器数量)
如果出于性能考虑,
- 对于简单操作推荐使用外部迭代手动实现,
- 对于复杂操作,推荐使用Stream API,
- 在多核情况下,推荐使用并行Stream API来发挥多核优势,单核情况下不建议使用并行Stream API。
如果出于代码简洁性考虑,使用Stream API能够写出更短的代码。即使是从性能方面说,尽可能的使用Stream API也另外一个优势,那就是只要Java Stream类库做了升级优化,代码不用做任何修改就能享受到升级带来的好处。