我刚接触Java 8,对其API还不是很了解,但我进行了一次小型的非正式基准测试,比较了新的Streams API和老旧的Collections在性能上的差异。
测试包括对一个整型列表进行过滤,并对每个偶数计算平方根,将其存储在一个结果为Double
类型的列表中。
以下是代码:
public static void main(String[] args) {
//Calculating square root of even numbers from 1 to N
int min = 1;
int max = 1000000;
List<Integer> sourceList = new ArrayList<>();
for (int i = min; i < max; i++) {
sourceList.add(i);
}
List<Double> result = new LinkedList<>();
//Collections approach
long t0 = System.nanoTime();
long elapsed = 0;
for (Integer i : sourceList) {
if(i % 2 == 0){
result.add(Math.sqrt(i));
}
}
elapsed = System.nanoTime() - t0;
System.out.printf("Collections: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
//Stream approach
Stream<Integer> stream = sourceList.stream();
t0 = System.nanoTime();
result = stream.filter(i -> i%2 == 0).map(i -> Math.sqrt(i)).collect(Collectors.toList());
elapsed = System.nanoTime() - t0;
System.out.printf("Streams: Elapsed time:\t\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
//Parallel stream approach
stream = sourceList.stream().parallel();
t0 = System.nanoTime();
result = stream.filter(i -> i%2 == 0).map(i -> Math.sqrt(i)).collect(Collectors.toList());
elapsed = System.nanoTime() - t0;
System.out.printf("Parallel streams: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
}.
这是双核机器的结果:
Collections: Elapsed time: 94338247 ns (0,094338 seconds)
Streams: Elapsed time: 201112924 ns (0,201113 seconds)
Parallel streams: Elapsed time: 357243629 ns (0,357244 seconds)
针对这个特定的测试,流比集合慢大约两倍,并且并行化没有帮助(或者我使用的方式不对?)。
问题:
- 这个测试公平吗?我有犯任何错误吗?
- 流比集合慢吗?有人做过好的正式基准测试吗?
- 应该选择哪种方法?
更新结果。
我在JVM预热后运行了1000次测试(1k次迭代),如@pveentjer建议的那样:
Collections: Average time: 206884437,000000 ns (0,206884 seconds)
Streams: Average time: 98366725,000000 ns (0,098367 seconds)
Parallel streams: Average time: 167703705,000000 ns (0,167704 seconds)
在这种情况下,流更具性能优势。我想知道在运行时仅调用过滤函数一两次的应用程序中会观察到什么。
IntStream
吗? - Mark RotteveeltoList
应该可以并行运行,即使它正在收集到一个非线程安全的列表中,因为不同的线程将会在合并之前收集到线程限定的中间列表。 - Stuart Marks