如何在Stream上短路减少?

nec*_*cer 10 java java-8 java-stream

假设我有一个布尔值流,我正在编写的reduce操作是||(OR).我能否以一种方式编写它,以便在true遇到值时至少放弃对某些元素的评估?

我正在寻找一些优化(可能是它是一个并行流),不一定是完全优化,虽然后者会很棒.

Pet*_*rey 19

我怀疑你想要这种类型的构造.

// stop when any element evaluates to true
boolean any = stream.anyMatch(t -> t);
Run Code Online (Sandbox Code Playgroud)

你可以偷看这个

Stream.of(1, 2, 3, 4).peek(System.out::println).anyMatch(i -> i == 2);
Run Code Online (Sandbox Code Playgroud)

版画

1
2
Run Code Online (Sandbox Code Playgroud)

对于一个并行的例子

AtomicInteger count = new AtomicInteger();
IntStream.range(0, 1000).parallel().peek(t -> count.incrementAndGet()).anyMatch(i -> i == 2);
System.out.println("count: " + count);
Run Code Online (Sandbox Code Playgroud)

打印一个像

count: 223
Run Code Online (Sandbox Code Playgroud)

具体数量各不相同.

对于referencePipeline,anyMatch调用

@Override
public final boolean anyMatch(Predicate<? super P_OUT> predicate) {
    return evaluate(MatchOps.makeRef(predicate, MatchOps.MatchKind.ANY));
}
Run Code Online (Sandbox Code Playgroud)

这称之为

public static <T> TerminalOp<T, Boolean> makeRef(Predicate<? super T> predicate,
        MatchKind matchKind) {
    Objects.requireNonNull(predicate);
    Objects.requireNonNull(matchKind);
    class MatchSink extends BooleanTerminalSink<T> {
        MatchSink() {
            super(matchKind);
        }

        @Override
        public void accept(T t) {
            if (!stop && predicate.test(t) == matchKind.stopOnPredicateMatches) {
                stop = true;
                value = matchKind.shortCircuitResult;
            }
        }
    }

    return new MatchOp<>(StreamShape.REFERENCE, matchKind, MatchSink::new);
}
Run Code Online (Sandbox Code Playgroud)

你可以在哪里开始看到短路代码.

  • @Holger我同意,这就是为什么我在一次运行中得到`223`并且"确切的数字不同"我依赖于窥视可能显示流被短路的事实. (4认同)