我已经看到了
Java 8流API的一些takeWhile实现,但它们似乎都将流转换为非并行流.例如
this一个:
static <T> Spliterator<T> takeWhile(
Spliterator<T> splitr, Predicate<? super T> predicate) {
return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
boolean stillGoing = true;
@Override public boolean tryAdvance(Consumer<? super T> consumer) {
if (stillGoing) {
boolean hadNext = splitr.tryAdvance(elem -> {
if (predicate.test(elem)) {
consumer.accept(elem);
} else {
stillGoing = false;
}
});
return hadNext && stillGoing;
}
return false;
}
};
}
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}
这里是StreamSupport.stream(takeWhile(stream.spliterator(),predicate),false);将传递给takeWhile的流转换为顺序流.是否有人知道支持并行流的实现,或者如何修改此代码以使其维护/支持并行流?
最佳答案 如果知道您的源是无序的,那么以下实现应该有效:
static final class UnorderedTakeWhileSpliterator<T> implements Spliterator<T>, Consumer<T>, Cloneable {
private final Predicate<? super T> predicate;
private final AtomicBoolean checked = new AtomicBoolean();
private Spliterator<T> source;
private T cur;
UnorderedTakeWhileSpliterator(Spliterator<T> source, Predicate<? super T> predicate) {
this.predicate = predicate;
this.source = source;
}
@Override
public void accept(T t) {
this.cur = t;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (!checked.get() && source.tryAdvance(this)) {
if (predicate.test(cur)) {
action.accept(cur);
return true;
} else {
checked.set(true);
}
}
return false;
}
@Override
public Spliterator<T> trySplit() {
Spliterator<T> prefix = source.trySplit();
if(prefix == null) {
return null;
}
if(checked.get()) {
return Spliterators.emptySpliterator();
}
UnorderedTakeWhileSpliterator<T> clone;
try {
clone = (UnorderedTakeWhileSpliterator<T>) clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
clone.source = prefix;
return clone;
}
@Override
public long estimateSize() {
return source.estimateSize();
}
@Override
public int characteristics() {
return source.characteristics() & (DISTINCT | SORTED | NONNULL);
}
@Override
public Comparator<? super T> getComparator() {
return source.getComparator();
}
}
使用以下方法创建流:
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return StreamSupport.stream(UnorderedTakeWhileSpliterator<>(stream.spliterator(), predicate), stream.isParallel());
}
有序实现会更加棘手,因为它应该缓冲非前缀项并将取消传播到后缀.像这样的东西在JDK-9中实现(不是作为分裂器,而是作为普通的流操作),但我怀疑即使这个棘手的实现在许多情况下也会胜过顺序流.