Loading... 在Java 8中引入了Stream API,我们在对集合进行操作时可以运用函数式编程的思想,用户只需要考虑“做什么”,而不需要考虑“怎么做”,函数式编程固然是简洁的,那么与传统的循环结构相比较,Stream API能不能在简洁的同时提高效率呢? ## 测试方法 testTime方法使用Runnable接口,利用System.nanoTime方法计算程序运行时间 ```JAVA public static void testTime(Runnable runnable) { long stime = System.nanoTime(); runnable.run(); long etime = System.nanoTime(); System.out.println("time" + (etime - stime)); } ``` 用于测试的集合存入一组随机数 ```java ArrayList<Double> list1 = new ArrayList<>(); for (int i = 0; i < 10e7; ++i) { list1.add(Math.random()); } ``` 对于每一种遍历结构,使用testTime方法测试时间,将每次遍历得到的值打印出来 ```java testTime(() -> { for (int i = 0; i < list1.size(); ++i) { System.out.println(list1.get(i)); } }); testTime(() -> { for (Double d : list1) { System.out.println(d); } }); testTime(() -> list1.forEach(System.out::println)); testTime(() -> list1.stream().forEach(System.out::println)); testTime(() -> list1.parallelStream().forEach(System.out::println)); ``` 同时为了防止jvm优化加入-XX:CompileThreshold=0 -XX:+TieredCompilation参数关闭jvm优化 ## 测试结果 因为实际环境的影响,测试的结果只是一个大概的范围,并不准确,不过仍然具有一定的参考价值,以下是不同数据量的测试结果 | 单位:毫秒(ms) | 1K | 1W | 10W | 100W | 1000W | | :--------------------: | :---: | :---: | :----: | :-----: | :------: | | for | 13.79 | 38.84 | 198.35 | 1404.31 | 13107.81 | | forEach | 3.92 | 21.56 | 150.82 | 1274.32 | 12771.57 | | ArrayList.forEach | 3.90 | 21.32 | 163.45 | 1302.86 | 12619.82 | | stream.forEach | 3.10 | 16.80 | 144.16 | 1298.58 | 12678.98 | | parallelStream.forEach | 6.74 | 27.52 | 214.81 | 1758.13 | 17271.42 | 其实这几种形式的效率和数据量有关系,在数据量较少时(0-100W),传统的for循环和foreach效率都是比较高的,而在数据量较大时(接近1000W),这时使用StreamAPI的效率就要远远大于传统循环了,特别的,因为Stream是串行操作,对于数据量巨大时,可以使用parallelStream(异步多线程),但同时也要考虑到并行带来的后果(如数据是否有序,是否线程安全等等),这也就是为什么在本例中parallelStream的速度远不如其他的原因(System.out.println是一个线程安全方法)。 总之,在一般的场景中,for循环以及foreach循环足够使用,并且性能很不错,只有当数据量巨大时,StreamAPI才是性能角度更优的选择,当然,如果你喜欢更简洁的代码逻辑,使用StreamAPI有何不可呢? © 允许规范转载 打赏 赞赏作者 微信 赞