我想檢索並從Java 8 Stream
中刪除下一個項目,但未關閉此Stream
。從Java 8流獲取下一個項目
Stream<Integer> integerStream = Stream.iterate(0, x -> new Integer(x + 1));
Integer zero = integerStream.getNext(); // 0
Integer one = integerStream.getNext(); // 1
...
這可能嗎?
我想檢索並從Java 8 Stream
中刪除下一個項目,但未關閉此Stream
。從Java 8流獲取下一個項目
Stream<Integer> integerStream = Stream.iterate(0, x -> new Integer(x + 1));
Integer zero = integerStream.getNext(); // 0
Integer one = integerStream.getNext(); // 1
...
這可能嗎?
根據Stuart's answer和Iterator-to-Stream conversion,我想出了下面的快速和骯髒的包裝類。它沒有經過測試,也不是線程安全的,但它提供了我目前需要的內容,並且保留這個流「打開」。
PeelingStream<T>
提供了一種方法T getNext()
遮蔽掉someWrappedStream.iterator()
的終端流操作語義:
public class PeelingStream<T> implements Stream<T> {
private Stream<T> wrapped;
public PeelingStream(Stream<T> toBeWrapped) {
this.wrapped = toBeWrapped;
}
public T getNext() {
Iterator<T> iterator = wrapped.iterator();
T next = iterator.next();
Iterable<T> remainingIterable =() -> iterator;
wrapped = StreamSupport.stream(remainingIterable.spliterator(),
false);
return next;
}
///////////////////// from here, only plain delegate methods
public Iterator<T> iterator() {
return wrapped.iterator();
}
public Spliterator<T> spliterator() {
return wrapped.spliterator();
}
public boolean isParallel() {
return wrapped.isParallel();
}
public Stream<T> sequential() {
return wrapped.sequential();
}
public Stream<T> parallel() {
return wrapped.parallel();
}
public Stream<T> unordered() {
return wrapped.unordered();
}
public Stream<T> onClose(Runnable closeHandler) {
return wrapped.onClose(closeHandler);
}
public void close() {
wrapped.close();
}
public Stream<T> filter(Predicate<? super T> predicate) {
return wrapped.filter(predicate);
}
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
return wrapped.map(mapper);
}
public IntStream mapToInt(ToIntFunction<? super T> mapper) {
return wrapped.mapToInt(mapper);
}
public LongStream mapToLong(ToLongFunction<? super T> mapper) {
return wrapped.mapToLong(mapper);
}
public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
return wrapped.mapToDouble(mapper);
}
public <R> Stream<R> flatMap(
Function<? super T, ? extends Stream<? extends R>> mapper) {
return wrapped.flatMap(mapper);
}
public IntStream flatMapToInt(
Function<? super T, ? extends IntStream> mapper) {
return wrapped.flatMapToInt(mapper);
}
public LongStream flatMapToLong(
Function<? super T, ? extends LongStream> mapper) {
return wrapped.flatMapToLong(mapper);
}
public DoubleStream flatMapToDouble(
Function<? super T, ? extends DoubleStream> mapper) {
return wrapped.flatMapToDouble(mapper);
}
public Stream<T> distinct() {
return wrapped.distinct();
}
public Stream<T> sorted() {
return wrapped.sorted();
}
public Stream<T> sorted(Comparator<? super T> comparator) {
return wrapped.sorted(comparator);
}
public Stream<T> peek(Consumer<? super T> action) {
return wrapped.peek(action);
}
public Stream<T> limit(long maxSize) {
return wrapped.limit(maxSize);
}
public Stream<T> skip(long n) {
return wrapped.skip(n);
}
public void forEach(Consumer<? super T> action) {
wrapped.forEach(action);
}
public void forEachOrdered(Consumer<? super T> action) {
wrapped.forEachOrdered(action);
}
public Object[] toArray() {
return wrapped.toArray();
}
public <A> A[] toArray(IntFunction<A[]> generator) {
return wrapped.toArray(generator);
}
public T reduce(T identity, BinaryOperator<T> accumulator) {
return wrapped.reduce(identity, accumulator);
}
public Optional<T> reduce(BinaryOperator<T> accumulator) {
return wrapped.reduce(accumulator);
}
public <U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner) {
return wrapped.reduce(identity, accumulator, combiner);
}
public <R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
return wrapped.collect(supplier, accumulator, combiner);
}
public <R, A> R collect(Collector<? super T, A, R> collector) {
return wrapped.collect(collector);
}
public Optional<T> min(Comparator<? super T> comparator) {
return wrapped.min(comparator);
}
public Optional<T> max(Comparator<? super T> comparator) {
return wrapped.max(comparator);
}
public long count() {
return wrapped.count();
}
public boolean anyMatch(Predicate<? super T> predicate) {
return wrapped.anyMatch(predicate);
}
public boolean allMatch(Predicate<? super T> predicate) {
return wrapped.allMatch(predicate);
}
public boolean noneMatch(Predicate<? super T> predicate) {
return wrapped.noneMatch(predicate);
}
public Optional<T> findFirst() {
return wrapped.findFirst();
}
public Optional<T> findAny() {
return wrapped.findAny();
}
}
一個小測試:
@Test
public void testPeelingOffItemsFromStream() {
Stream<Integer> infiniteStream = Stream.iterate(0, x -> x + 1);
PeelingStream<Integer> peelingInfiniteStream = new PeelingStream<>(infiniteStream);
Integer one = peelingInfiniteStream.getNext();
assertThat(one, equalTo(0));
Integer two = peelingInfiniteStream.getNext();
assertThat(two, equalTo(1));
Stream<Integer> limitedStream = peelingInfiniteStream.limit(3); // 2 3 4
int sumOf234 = limitedStream.mapToInt(x -> x.intValue()).sum();
assertThat(sumOf234, equalTo(2 + 3 + 4));
}
是的,有一種方法可以做到這一點,但有一些限制。
Stream<Integer> infiniteStream = Stream.iterate(0, x -> new Integer(x + 1));
Iterator<Integer> iter = infiniteStream.iterator();
Integer zero = iter.next();
Integer one = iter.next();
或者,
Stream<Integer> infiniteStream = Stream.iterate(0, x -> new Integer(x + 1));
Spliterator<Integer> spliterator = infiniteStream.spliterator();
spliterator.tryAdvance(i -> System.out.println(i)); // zero
spliterator.tryAdvance(i -> System.out.println(i)); // one
給定一個Stream
,有可能從它得到一個Iterator
或Spliterator
,或者查詢它是否是一個平行流等,這些是本BaseStream
接口上定義, Stream
超級界面,這使他們有點容易錯過。
在這種情況下,我們知道流是無限的,所以沒有必要調用迭代器的hasNext()
方法或檢查Spliterator的tryAdvance()
限制的返回值是兩者的iterator()
和spliterator()
方法Stream
是終端操作這意味着在它們被調用之後,返回的迭代器或Spliterator可獨佔訪問Stream所表示的值。此流上的其他操作(例如filter
或map
等等)是不允許的,將會遇到IllegalStateException
。
如果你想剝離第一對夫婦的元素,然後重新開始流處理,你可以把一個spliterator迴流,像這樣:
Stream<Integer> stream2 = StreamSupport.stream(spliterator, false);
這可能會爲一些事情做工精細,但我我不確定我會推薦這種技術。我認爲它增加了一些額外的對象,因此在生成下一個元素的路徑中增加了額外的方法調用。
編者按(不涉及您的問題):
new Integer(val)
。取而代之的是使用Integer.valueOf(val)
,如果可用,它將重新使用盒裝整數,對於-128到127範圍內的值,這通常爲真。IntStream
而不是Stream<Integer>
,它完全避免了裝箱開銷。它沒有完整的流操作,但它確實有iterate()
,它具有一個在原始值int
上運行的函數。或者你也可以使用'x - > x + 1',它更短,並且使用'Integer.valueOf'(剛纔用8u25和'javap -c -p'來驗證)。 – 2014-10-27 20:56:25
您是否在考慮實際使用的刪除的項目,或丟棄它們?對於後者,'.skip(n)'是實現它的方法。 – 2014-10-27 20:57:29