Pau*_*len 12 java java-8 java-stream
或者,有没有更好的方法来做到这一点,我错过了?我想基于供应商创建一个流(通常是无限的),但是当供应商返回null时,流终止.我自己做了这个,但是完成一个非常简单的概念似乎是相当多的工作.
public class NullTerminatedStreamFactory {
static int characteristics = Spliterator.ORDERED | Spliterator.DISTINCT;
public static<T> Stream<T> makeNullTerminatedStream(Supplier<T> supplier) {
return StreamSupport.stream(new NullTerminatedSpliteratorFromSupplier<>(supplier, Long.MAX_VALUE, characteristics), false);
}
static class NullTerminatedSpliteratorFromSupplier<T> extends Spliterators.AbstractSpliterator<T> {
public NullTerminatedSpliteratorFromSupplier(Supplier<T> supplier, long est, int additionalCharacteristics) {
super(est, additionalCharacteristics);
this.supplier = supplier;
}
public Supplier<T> supplier;
@Override
public boolean tryAdvance(Consumer<? super T> action) {
T next = supplier.get();
if (next != null) {
action.accept(next);
return true;
}
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了记录,我正在使用它,基本上从BlockingQueue创建一个Stream:
NullTerminatedStreamFactory.makeNullTerminatedStream(() -> {
try {
BlockingQueue<Message> queue = getBlockingQueue();
return queue.poll(1, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("Exception while trying to get message from queue", e);
}
return null;
});
Run Code Online (Sandbox Code Playgroud)
您已经找到了一个完全有效的手工制作实现.
正如评论中提到的,Java 9似乎添加了一种takeWhile(Predicate)方法.在此之前,您可以使用第三方库来实现以下内容takeWhile():
jOOλ有limitWhile(),它做同样的事情:
Seq.generate(supplier).limitWhile(Objects::nonNull);
Run Code Online (Sandbox Code Playgroud)
(免责声明,我为jOOλ背后的公司工作)
Javaslang实现了自己的Stream类,它的灵感来自Scala集合,因此具有takeWhile()
Stream.gen(supplier).takeWhile(Objects::nonNull);
Run Code Online (Sandbox Code Playgroud)
Functional Java还附带了自己的Stream实现,它有一个takeWhile()方法:
Stream.fromFunction(i -> supplier.get()).takeWhile(o -> o != null);
Run Code Online (Sandbox Code Playgroud)