java - Java Stream 的工作速度比 for 循环慢
问题描述
有人告诉我 Java Stream 是处理大量数据的好选择,我最近做了一个比较测试。然而测试结果出乎意料:
问题来自 CodeWar:
假设有一个地铁最初有 100 人,每一站都有几个人上地铁,几个人下车。目标是统计经过大量停靠后仍留在地铁中的人数(100000)。
这是我的代码:
import java.util.ArrayList;
public class Metro1 {
private final static int STOPS = 100000;
private static ArrayList<int[]> metro = new ArrayList<int[]>();
public static int sum1() {
int sum = 0;
for(int[] x: metro) {
sum +=x[0] - x[1];
}
return sum;
}
public static int sum2() {
return metro.stream()
.mapToInt(x -> x[0]-x[1])
.sum();
}
public static void main(String[] args) {
long start=0;
long end = 0;
metro.add(new int[] {100,0});
for(int i=1;i<STOPS;i++) {
int in = (int) Math.round(Math.random() * 10);
int out = (int) Math.round(Math.random() * 10);
metro.add(new int[] {in,out});
}
System.out.println("Stops: " + metro.size());
start = System.currentTimeMillis();
System.out.println("sum1: " + sum1());
end = System.currentTimeMillis();
System.out.println("sum1 (for loop): " + String.valueOf(end-start) + " milliseconds.");
start = System.currentTimeMillis();
System.out.println("sum2: " + sum2());
end = System.currentTimeMillis();
System.out.println("sum1 (stream): " + String.valueOf(end-start) + " milliseconds.");
}
}
我在 Eclipse 中运行了代码,发现 sum1 比 sum2 快得多:
Stops: 100000
sum1: 79
sum1 (for loop): 6 milliseconds.
sum2: 79
sum1 (stream): 68 milliseconds.
我认为代码很简单,但为什么流比 for 循环慢?
谢谢,
亚历克斯
解决方案
就像regexes
特定的本地解析器可以更快一样,流可以提供一种快速简洁的数据处理方式。流的优点之一是在处理元素时可以最小化中间数据结构。另一个是parallel
评论中已经提到的方面。
但至于你的例子。
- 依靠使用内部时钟的简单性能测试(即使我也这样做)并不是准确评估性能的最佳方法。使用Java Microbench Harness之类的东西进行测试。
至于您的结果,请尝试以下方法:
- 更改
STOPS
为100_000_000
- 将您的流修改为
return metro.stream().parallel() .mapToInt(x -> x[0]-x[1]) .sum();
- 更改
这是我的结果Windows, quad core i7 laptop
Stops: 100000000
sum1: -7073
sum1 (for loop): 908 milliseconds.
sum2: -7073
sum1 (stream): 518 milliseconds.
推荐阅读
- android - 我想将互联网上的图像从主要活动显示到另一个活动?
- c# - Mongo c# ReplaceOne 和 FindOneAndReplace
- java - Spring Data JPA + Lombok = UnsupportedOperationException 在保存期间
- python - 如何从python中的文件中读取“好”
- c# - 具有正两位数随机数的数组
- python - 美丽的汤 - 从多个页面获取文本
- bluetooth - 蓝牙资源管理器不记得 Macbook 上的 AptX 选择
- swift - 如何在空的 UITableView 中水平和垂直居中图像?
- javascript - 如何从数组中删除完整的唯一值
- widget - 将多边形数据添加到 ThingsBoard 上的 OSM 地图