【发布时间】:2014-07-31 14:37:57
【问题描述】:
我已经使用 Java 8 的 lambda 和流有一段时间了,因为我的硕士学位项目和我注意到一些在互联网上没有广泛讨论的东西。我正在使用 Netbeans 进行开发,并且多次建议更改“老式”风格以支持这两个新的构造函数。但我想知道这些建议是否真的有用。要点是:
- 易读性
也许是习惯问题,但如果您使用嵌套的 lambda,那么了解正在发生的事情可能会成为一场噩梦。
- 可测试性
由于 Netbeans 的建议,我们倾向于将 for 循环更改为流的 foreach 调用,但是在可测试性方面有一个微妙但非常危险的副作用。如果您的代码在 foreach 块内失败,IDE(实际上是编译器)根本不知道错误发生在哪一行,指向块的开头。此外,由于我们无法控制计算和内部循环,因此调试代码更加困难。
- 性能
同样,IDE 总是建议将累积更改为一种 map reduce 算法。后者看起来更复杂,所以我创建了一个简单的测试来检查这种方法有多好。令人惊讶的是,它慢了很多!
代码如下:
public class Java8Kata {
public static void main(String[] args) {
System.out.println("Generating random numbers...");
final Collection<Number> numbers = getRandomNumbers();
System.out.println("Starting comparison...");
for (int i = 0; i < 20; i++) {
getTotalConventionalStyle(numbers);
getTotalNewStyle(numbers);
}
}
public static void getTotalConventionalStyle(Collection<Number> numbers) {
long startTime = System.nanoTime();
System.out.println("\n\nstarting conventional...");
double total = 0;
for (Number number : numbers) {
total += number.doubleValue();
}
System.out.println("total = " + total);
System.out.println("finish conventional:" + getPeriod(startTime) + " seconds");
}
public static void getTotalNewStyle(Collection<Number> numbers) {
long startTime = System.nanoTime();
System.out.println("\n\nstarting new style ...");
double total = 0;
//netbeans conversion
total = numbers.parallelStream().map((number) -> number.doubleValue()).reduce(total, (accumulator, _item) -> accumulator + _item);
System.out.println("total = " + total);
System.out.println("finish new style:" + getPeriod(startTime) + " seconds");
}
public static Collection<Number> getRandomNumbers() {
Collection<Number> numbers = new ArrayList<>();
for (long i = 0; i < 9999999; i++) {
double randomInt = 9999999.0 * Math.random();
numbers.add(randomInt);
}
return numbers;
}
public static String getPeriod(long startTime) {
long time = System.nanoTime() - startTime;
final double seconds = ((double) time / 1000000000);
return new DecimalFormat("#.##########").format(seconds);
}
}
为了确保结果一致,我已经进行了 20 次比较。
他们在这里:
生成随机数... 开始比较... 开始常规... 总计 = 5.000187629072326E13 完成常规:0.309586459 秒 开始新风格... 总计 = 5.000187629073409E13 完成新样式:20.862798586 秒 开始常规... 总计 = 5.000187629072326E13 完成常规:0.316218488 秒 开始新风格... 总计 = 5.000187629073409E13 完成新样式:20.594838025 秒 [...]进行深入的性能测试不是我的目标,我只是想看看 Netbeans 是否对我有帮助。
作为结论,我可以说您应该谨慎使用这些新结构,由您自行决定,而不是遵循 IDE 建议。
【问题讨论】:
-
你是在问一个问题并在回答它,还是你实际上在这里问了什么?
-
我的结论只是一个观点,不一定是被引导到错误假设问题的最佳答案。我希望看到其他开发人员如何面对我指出的问题。
-
这些功能都不能提高性能。他们怎么可能击败紧密的累积循环。他们在那里是为了代码质量。 (而且减少对代码质量没有帮助。)
标签: lambda java-8 java-stream