为了学习Java,我正致力于解决这个问题 Project Euler's problem 23 我需要找到所有不能正整数的总和 写作两个数字的总和。我的解决方案使用Java 8流。一世 不会通过在这里发布实际答案来破坏它,但我会讨论我的 达成解决方案的策略。
首先,我使用IntStream创建一个包含大量数字的列表:
List<Integer> abundants = IntStream.range(1, EULER23_MAX)
.filter(i -> Util.sumOfDivisors(i) > i)
.boxed()
.collect(Collectors.toList());
然后,根据列表,我创建了一组2个丰度数较低的总和 比最大:
private Set<Integer> calcSumsOfTwoAbundants(List<Integer> abundants) {
Set<Integer> iset = new HashSet<>();
Integer[] arr = abundants.toArray(new Integer[abundants.size()]);
for (int i = 0; i < arr.length - 2; i++) {
for (int j = i; j < arr.length - 1; j++) {
int sum = arr[i] + arr[j];
if (sum <= EULER23_MAX) {
iset.add(sum);
}
}
}
return iset;
}
最后,我生成另一个流,过滤掉低于的所有数字 存在于两个丰度的总和中的最大值,我总结得到 结果。
result = IntStream.range(1, EULER23_MAX)
.filter(x -> !sumsOfTwoAbundants.contains(x))
.sum();
我的问题是:如何将calcSumsOfTwoAbundants
中的逻辑编码为
使用流Fluent语法而不是嵌套的for
循环?我试过了
几个不同的东西,但我不断得到“流已经
关闭“错误信息或完全错误的结果。我也明白了
嵌套的for
循环可能比使用流更快,但这是
纯粹是一种智力锻炼...这就是我现在所拥有的:
// wrong results
private Set<Integer> calcSumsOfTwoAbundantsAlt(List<Integer> abundants) {
return abundants.stream()
.filter(i -> abundants.stream()
.anyMatch(j -> (i + j) <= EULER23_MAX))
.collect(Collectors.toSet());
}
答案 0 :(得分:2)
最直接的等价物是用IntStream.range
替换每个for循环并将其与flatMap
嵌套:
Set<Integer> iset = IntStream.range(0, arr.length - 2)
.flatMap(i -> IntStream.range(i, arr.length - 1)
.map(j -> arr[i] + arr[j]).filter(s -> s <= EULER23_MAX))
.boxed().collect(Collectors.toSet());