代码之家  ›  专栏  ›  技术社区  ›  λ Jonas Gorauskas

将嵌套的循环嵌套到Java流的同一列表中

  •  2
  • λ Jonas Gorauskas  · 技术社区  · 8 年前

    为了学习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 到 使用流流利的语法而不是嵌套的 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());
    }
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Sean Van Gorder    8 年前

    最直接的等价物是将每个for循环替换为 IntStream.range 和他们一起筑巢 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());