我在解决欧拉计划的第205题时发现了这个问题。 问题如下:
我突出显示的代码使用了简单的
如果我用替换流代码的方式来代替看起来完全相同的预流等效代码:
Peter有9个四面体骰子,每个骰子的面数为1、2、3、4。 Colin有6个六面体骰子,每个骰子的面数为1、2、3、4、5、6。
Peter和Colin掷骰子并比较点数:最高点数获胜。 如果总分相等,则结果为平局。
Pyramidal Pete击败Cubic Colin的概率是多少? 将您的答案四舍五入为小数点后七位,格式为0.abcdefg
我使用Guava编写了一个简单的解决方案:
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
public class Problem205 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<Integer> peter = Sets.cartesianProduct(Collections.nCopies(9, ImmutableSet.of(1, 2, 3, 4)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
List<Integer> colin = Sets.cartesianProduct(Collections.nCopies(6, ImmutableSet.of(1, 2, 3, 4, 5, 6)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
long startTime2 = System.currentTimeMillis();
// IMPORTANT BIT HERE! v
long solutions = peter
.stream()
.mapToLong(p -> colin
.stream()
.filter(c -> p > c)
.count())
.sum();
// IMPORTANT BIT HERE! ^
System.out.println("Counting solutions took " + (System.currentTimeMillis() - startTime2) + "ms");
System.out.println("Solution: " + BigDecimal
.valueOf(solutions)
.divide(BigDecimal
.valueOf((long) Math.pow(4, 9) * (long) Math.pow(6, 6)),
7,
RoundingMode.HALF_UP));
System.out.println("Found in: " + (System.currentTimeMillis() - startTime) + "ms");
}
}
我突出显示的代码使用了简单的
filter()
,count()
和sum()
。在Java 9中运行速度似乎比Java 8快得多。具体来说,在我的机器上,Java 8在37465ms内计算出解决方案。而Java 9只需要大约16000ms,无论我是运行使用Java 8编译的文件还是使用Java 9编译的文件都是如此。如果我用替换流代码的方式来代替看起来完全相同的预流等效代码:
long solutions = 0;
for (Integer p : peter) {
long count = 0;
for (Integer c : colin) {
if (p > c) {
count++;
}
}
solutions += count;
}
它在大约35000ms内计算出解决方案,Java 8和Java 9之间没有可测量的差异。
我错过了什么?为什么Java 9中流代码如此快,而for
循环不是?
我正在运行Ubuntu 16.04 LTS 64位。我的Java 8版本:
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
我的Java 9版本:
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)