如何在同一个java流上同时调用takewhile和dropwhile

o7jaxewo  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(244)

如何在同一个java流上组合takewhile和dropwhile?
我想使用或实现scala的span方法。
到目前为止,我有以下代码,但作为练习,我尝试尽可能使用流):

Iterator<T> iter = ...
// takeWhile(pred).forEach(foo)
while (iter.hasNext()) {
    T elem = iter.next();
    if (!pred(elem)) {
        break;
    }
    foo(elem);
}
// dropWhile(pred).forEach(bar)
iter.forEachRemaining(elem -> bar(elem));
w8f9ii69

w8f9ii691#

你不能使用 takeWhile 以及 dropWhile 在一个 Stream ,因为 Stream 只有一个用途,但你可以在 Iterable ,因为您可以从一个 Iterable .
根据您的需要,您可以执行所示逻辑尝试执行的操作,即根据条件第一次为真的时间执行两个操作之一。可以为此编写助手方法:

static <T> Consumer<T> span(Predicate<T> p, Consumer<T> prefix, Consumer<T> suffix) {
    return new Consumer<>() {
        private boolean conditionMet;
        @Override
        public void accept(T t) {
            if (! conditionMet) {
                if (p.test(t)) {
                    prefix.accept(t);
                    return;
                }
                conditionMet = true;
            }
            suffix.accept(t);
        }
    };
}

然后你会像这样用在 Stream :

Stream<T> stream = ...;

stream.forEachOrdered(span(elem -> pred(elem),
                           elem -> foo(elem),
                           elem -> bar(elem)));

// Or the method reference version:
stream.forEachOrdered(span(MyClass::pred, MyClass::foo, MyClass::bar));

那会叫 foo() 对于每个元素 pred() 返回true,然后调用 bar() 在所有剩余的元素上。
请注意 span 需要有序处理,从而破坏了并行处理的流优势。

相关问题