如何根据某些条件中途停止减少操作?

How to stop a reduce operation mid way based on some condition?

如何根据某些条件中途停止reduce操作?

例如,我怎样才能找到整数列表中最大值的索引,然后才能达到 0。因此在下面的代码中,处理 list1 应该 return 4(第 5 个元素),而处理 list2 应该 return 1(第2个元素,因为8是0之前的5、8、3中的最大值)。

    List<Integer> list1 = Arrays.asList(5, 8, 3, 2, 10, 7);
    List<Integer> list2 = Arrays.asList(5, 8, 3, 0, 2, 10, 7);
    // This will work for list1 but not for list2
    IntStream.range(0, list1.size())
            .reduce((a, b) -> list1.get(a) < list1.get(b) ? b : a)
            .ifPresent(ix -> System.out.println("Index: " + ix));

Reduction 旨在处理一整套值,而不指定实际处理的顺序。在这方面,不可能“在 x 点停止”,因为这意味着处理顺序。

所以简单的回答就是,reduce不支持,所以,如果要限制搜索范围,先做限制:

List<Integer> list2 = Arrays.asList(5, 8, 3, 0, 2, 10, 7);
int limit=list2.indexOf(0);
IntStream.range(0, limit>=0? limit: list2.size())
        .reduce((a, b) -> list2.get(a) < list2.get(b) ? b : a)
        .ifPresent(ix -> System.out.println("Index: " + ix));

请注意,您可以使用 this answer 中描述的低级别 Spliterator 接口实现一种在特定条件下结束的新型 Stream,但我认为这不是努力会有回报。

从 Java 9 开始,您可以使用:

IntStream.range(0, list2.size())
    .takeWhile(ix -> list2.get(ix) != 0)
    .reduce((a, b) -> list2.get(a) < list2.get(b) ? b : a)
    .ifPresent(ix -> System.out.println("Index: " + ix));

takeWhile取决于前面流的遭遇顺序。由于IntStream.range产生的是有序流,因此保证只有遇到顺序中第一个不匹配元素之前的元素才会被后续归约使用。