【发布时间】:2020-04-11 14:32:37
【问题描述】:
我只是在尝试一些代码 sn-ps 并发现与使用 java 8 流相比,使用简单的 for 循环给了我更好的性能结果。现在,我可能在理解这些事情时遗漏了一些东西。我需要帮助理解差异。在下面添加我的代码。
//Following takes almost 3ms
public int[] testPerf(int[] nums, int[] index) {
List<Integer> arrayL = new ArrayList<>();
for(int i =0; i< index.length; i++){
arrayL.add(index[i], nums[i]);
}
return arrayL.stream().mapToInt(i -> i).toArray();
}
//Following takes almost 1ms
public int[] testPerf(int[] nums, int[] index) {
List<Integer> arrayL = new ArrayList<>();
for(int i =0; i< index.length; i++){
arrayL.add(index[i], nums[i]);
}
int [] result = new int[index.length];
for(int i =0; i< index.length; i++){
result[i] = arrayL.get(i);
}
return result;
}
编辑:开始
我想测试什么?在索引数组指定的索引处注入 nums 的元素,形成最终结果。
Input: nums = [0,1,2,3,4], index = [0,1,2,2,1]
Output: [0,4,1,3,2]
Explanation:
nums index target
0 0 [0]
1 1 [0,1]
2 2 [0,1,2]
3 2 [0,1,3,2]
4 1 [0,4,1,3,2]
编辑:结束
请注意,我已经用不同的输入测试了这些,并尝试了包含 2k+ 元素的数组,但带有 for 循环的代码仍然给了我更好的性能。
请指导是什么使其他代码花费更多时间? 还要指出我可以学习何时不使用 java 流的任何参考资料? (什么时候不要过于复杂?:))
【问题讨论】:
-
第一种方法应该是一行
return Arrays.stream(nums).toArray();- 你的代码不是最优的。其次,众所周知,微基准测试很难正确执行(而且您还没有包含导致您得出结论哪个更快的测试工具)。 -
Stream 并不能保证更好的性能,但可以保证更好的代码可读性。你可以看看 mapToInt underhood 是如何实现的。
-
"与使用 java 8 流相比,简单的 for 循环给了我更好的性能结果"几乎总是会这样,因为有一个使用流的开销很大。只有当循环中的工作很繁重,并且您启用了并行处理时,流才有可能胜过旧式循环。
-
你没有解释你是如何测试性能的。这就是为什么您的结果可能不正确的原因。看起来很奇怪:1)方法不仅包含您比较的功能,还包含附加代码。 2)你说的是 1 毫秒,3 毫秒。这是低于测试精度的范围。例如,进行 10 次测试,每次测试持续约 1 分钟。消除大偏差。然后取平均值。然后你有或多或少的现实比较。不过,for 可以更快。但是你会知道真实的画面。
-
@ElliottFrisch
return Arrays.stream(nums).toArray();真的吗?为什么不return nums.clone();,因为这将是相同结果的更快版本? --- 这仍然完全忽略了index参数,这可能是有原因的。
标签: java arrays java-8 java-stream