You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将同一列表的嵌套for循环改写为Java Stream实现

用Java Stream替代嵌套循环生成两个过剩数的和集合

你之前的尝试出错是因为逻辑方向完全不对——你的代码只是筛选出存在至少一个j使得i+j不超过最大值的过剩数i,然后把这些i收集到Set里,这和你要的“所有两个过剩数之和”的目标完全偏离了。我们需要的是生成所有符合条件的i+j组合,而不是筛选i本身。

正确的Stream实现方式

我们可以用flatMap来模拟嵌套循环的逻辑:对于每个过剩数i,生成所有满足i+j <= EULER23_MAX的j(和你原循环一样,从i开始遍历j,避免重复计算a+b和b+a这类等价组合),然后把每个i+j的结果平铺成一个单一流,最后收集到Set里去重。

代码如下:

private Set<Integer> calcSumsOfTwoAbundantsAlt(List<Integer> abundants) {
    int max = EULER23_MAX;
    return abundants.stream()
            .flatMap(i -> abundants.stream()
                    .filter(j -> j >= i) // 和原循环j=i的逻辑一致,避免重复组合
                    .map(j -> i + j)
                    .filter(sum -> sum <= max))
            .collect(Collectors.toSet());
}

代码细节解释

  1. flatMap的核心作用:如果用普通map,会得到Stream<Stream<Integer>>(每个i对应一个j的sum流),而flatMap能把这些嵌套流压平成一个连续的Stream<Integer>,这正是我们需要的所有和的集合。
  2. j >= i的过滤:和你原循环的j = i起始条件保持一致,利用加法交换律减少不必要的计算,避免生成重复的和。
  3. sum <= max的过滤:确保只收集不超过题目上限的和,和原逻辑完全对齐。

进阶优化(Java 9+)

因为你的过剩数列表是通过IntStream.range生成的,本身是升序排列的,我们可以用takeWhile提前截断流,一旦i+j超过最大值就停止遍历当前i对应的j,进一步提升效率:

private Set<Integer> calcSumsOfTwoAbundantsAlt(List<Integer> abundants) {
    int max = EULER23_MAX;
    return abundants.stream()
            .flatMap(i -> abundants.stream()
                    .filter(j -> j >= i)
                    .takeWhile(j -> i + j <= max) // 一旦sum超过上限就停止遍历
                    .map(j -> i + j))
            .collect(Collectors.toSet());
}

这样既完全复刻了原嵌套循环的逻辑,又用Stream语法完成了你的练习需求。

内容的提问来源于stack exchange,提问作者λ Jonas Gorauskas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:51:46