/*
* Copyright (C) 2015 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.math.LongMath;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.checkerframework.checker.nullness.qual.Nullable;
Static utility methods related to Stream
instances. Since: 21.0
/**
* Static utility methods related to {@code Stream} instances.
*
* @since 21.0
*/
@Beta
@GwtCompatible
public final class Streams {
Returns a sequential Stream
of the contents of iterable
, delegating to Collection.stream
if possible. /**
* Returns a sequential {@link Stream} of the contents of {@code iterable}, delegating to {@link
* Collection#stream} if possible.
*/
public static <T> Stream<T> stream(Iterable<T> iterable) {
return (iterable instanceof Collection)
? ((Collection<T>) iterable).stream()
: StreamSupport.stream(iterable.spliterator(), false);
}
Returns Collection.stream
. Deprecated: There is no reason to use this; just invoke collection.stream()
directly.
/**
* Returns {@link Collection#stream}.
*
* @deprecated There is no reason to use this; just invoke {@code collection.stream()} directly.
*/
@Deprecated
public static <T> Stream<T> stream(Collection<T> collection) {
return collection.stream();
}
Returns a sequential Stream
of the remaining contents of iterator
. Do not use iterator
directly after passing it to this method. /**
* Returns a sequential {@link Stream} of the remaining contents of {@code iterator}. Do not use
* {@code iterator} directly after passing it to this method.
*/
public static <T> Stream<T> stream(Iterator<T> iterator) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}
If a value is present in optional
, returns a stream containing only that element, otherwise returns an empty stream. /**
* If a value is present in {@code optional}, returns a stream containing only that element,
* otherwise returns an empty stream.
*/
public static <T> Stream<T> stream(com.google.common.base.Optional<T> optional) {
return optional.isPresent() ? Stream.of(optional.get()) : Stream.of();
}
If a value is present in optional
, returns a stream containing only that element, otherwise returns an empty stream. Java 9 users: use optional.stream()
instead.
/**
* If a value is present in {@code optional}, returns a stream containing only that element,
* otherwise returns an empty stream.
*
* <p><b>Java 9 users:</b> use {@code optional.stream()} instead.
*/
public static <T> Stream<T> stream(java.util.Optional<T> optional) {
return optional.isPresent() ? Stream.of(optional.get()) : Stream.of();
}
If a value is present in optional
, returns a stream containing only that element, otherwise returns an empty stream. Java 9 users: use optional.stream()
instead.
/**
* If a value is present in {@code optional}, returns a stream containing only that element,
* otherwise returns an empty stream.
*
* <p><b>Java 9 users:</b> use {@code optional.stream()} instead.
*/
public static IntStream stream(OptionalInt optional) {
return optional.isPresent() ? IntStream.of(optional.getAsInt()) : IntStream.empty();
}
If a value is present in optional
, returns a stream containing only that element, otherwise returns an empty stream. Java 9 users: use optional.stream()
instead.
/**
* If a value is present in {@code optional}, returns a stream containing only that element,
* otherwise returns an empty stream.
*
* <p><b>Java 9 users:</b> use {@code optional.stream()} instead.
*/
public static LongStream stream(OptionalLong optional) {
return optional.isPresent() ? LongStream.of(optional.getAsLong()) : LongStream.empty();
}
If a value is present in optional
, returns a stream containing only that element, otherwise returns an empty stream. Java 9 users: use optional.stream()
instead.
/**
* If a value is present in {@code optional}, returns a stream containing only that element,
* otherwise returns an empty stream.
*
* <p><b>Java 9 users:</b> use {@code optional.stream()} instead.
*/
public static DoubleStream stream(OptionalDouble optional) {
return optional.isPresent() ? DoubleStream.of(optional.getAsDouble()) : DoubleStream.empty();
}
Returns a Stream
containing the elements of the first stream, followed by the elements of the second stream, and so on. This is equivalent to Stream.of(streams).flatMap(stream -> stream)
, but the returned stream may perform better.
See Also:
/**
* Returns a {@link Stream} containing the elements of the first stream, followed by the elements
* of the second stream, and so on.
*
* <p>This is equivalent to {@code Stream.of(streams).flatMap(stream -> stream)}, but the returned
* stream may perform better.
*
* @see Stream#concat(Stream, Stream)
*/
@SafeVarargs
public static <T> Stream<T> concat(Stream<? extends T>... streams) {
// TODO(lowasser): consider an implementation that can support SUBSIZED
boolean isParallel = false;
int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL;
long estimatedSize = 0L;
ImmutableList.Builder<Spliterator<? extends T>> splitrsBuilder =
new ImmutableList.Builder<>(streams.length);
for (Stream<? extends T> stream : streams) {
isParallel |= stream.isParallel();
Spliterator<? extends T> splitr = stream.spliterator();
splitrsBuilder.add(splitr);
characteristics &= splitr.characteristics();
estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize());
}
return StreamSupport.stream(
CollectSpliterators.flatMap(
splitrsBuilder.build().spliterator(),
splitr -> (Spliterator<T>) splitr,
characteristics,
estimatedSize),
isParallel)
.onClose(
() -> {
for (Stream<? extends T> stream : streams) {
stream.close();
}
});
}
Returns an IntStream
containing the elements of the first stream, followed by the elements of the second stream, and so on. This is equivalent to Stream.of(streams).flatMapToInt(stream -> stream)
, but the returned stream may perform better.
See Also:
/**
* Returns an {@link IntStream} containing the elements of the first stream, followed by the
* elements of the second stream, and so on.
*
* <p>This is equivalent to {@code Stream.of(streams).flatMapToInt(stream -> stream)}, but the
* returned stream may perform better.
*
* @see IntStream#concat(IntStream, IntStream)
*/
public static IntStream concat(IntStream... streams) {
// TODO(lowasser): optimize this later
return Stream.of(streams).flatMapToInt(stream -> stream);
}
Returns a LongStream
containing the elements of the first stream, followed by the elements of the second stream, and so on. This is equivalent to Stream.of(streams).flatMapToLong(stream -> stream)
, but the returned stream may perform better.
See Also:
/**
* Returns a {@link LongStream} containing the elements of the first stream, followed by the
* elements of the second stream, and so on.
*
* <p>This is equivalent to {@code Stream.of(streams).flatMapToLong(stream -> stream)}, but the
* returned stream may perform better.
*
* @see LongStream#concat(LongStream, LongStream)
*/
public static LongStream concat(LongStream... streams) {
// TODO(lowasser): optimize this later
return Stream.of(streams).flatMapToLong(stream -> stream);
}
Returns a DoubleStream
containing the elements of the first stream, followed by the elements of the second stream, and so on. This is equivalent to Stream.of(streams).flatMapToDouble(stream -> stream)
, but the returned stream may perform better.
See Also:
/**
* Returns a {@link DoubleStream} containing the elements of the first stream, followed by the
* elements of the second stream, and so on.
*
* <p>This is equivalent to {@code Stream.of(streams).flatMapToDouble(stream -> stream)}, but the
* returned stream may perform better.
*
* @see DoubleStream#concat(DoubleStream, DoubleStream)
*/
public static DoubleStream concat(DoubleStream... streams) {
// TODO(lowasser): optimize this later
return Stream.of(streams).flatMapToDouble(stream -> stream);
}
Returns a stream in which each element is the result of passing the corresponding elementY of each of streamA
and streamB
to function
. For example:
Streams.zip(
Stream.of("foo1", "foo2", "foo3"),
Stream.of("bar1", "bar2"),
(arg1, arg2) -> arg1 + ":" + arg2)
will return Stream.of("foo1:bar1", "foo2:bar2")
.
The resulting stream will only be as long as the shorter of the two input streams; if one
stream is longer, its extra elements will be ignored.
Note that if you are calling Stream.forEach
on the resulting stream, you might want to consider using forEachPair
instead of this method.
Performance note: The resulting stream is not efficiently splittable.
This may harm parallel performance.
/**
* Returns a stream in which each element is the result of passing the corresponding elementY of
* each of {@code streamA} and {@code streamB} to {@code function}.
*
* <p>For example:
*
* <pre>{@code
* Streams.zip(
* Stream.of("foo1", "foo2", "foo3"),
* Stream.of("bar1", "bar2"),
* (arg1, arg2) -> arg1 + ":" + arg2)
* }</pre>
*
* <p>will return {@code Stream.of("foo1:bar1", "foo2:bar2")}.
*
* <p>The resulting stream will only be as long as the shorter of the two input streams; if one
* stream is longer, its extra elements will be ignored.
*
* <p>Note that if you are calling {@link Stream#forEach} on the resulting stream, you might want
* to consider using {@link #forEachPair} instead of this method.
*
* <p><b>Performance note:</b> The resulting stream is not <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>.
* This may harm parallel performance.
*/
public static <A, B, R> Stream<R> zip(
Stream<A> streamA, Stream<B> streamB, BiFunction<? super A, ? super B, R> function) {
checkNotNull(streamA);
checkNotNull(streamB);
checkNotNull(function);
boolean isParallel = streamA.isParallel() || streamB.isParallel(); // same as Stream.concat
Spliterator<A> splitrA = streamA.spliterator();
Spliterator<B> splitrB = streamB.spliterator();
int characteristics =
splitrA.characteristics()
& splitrB.characteristics()
& (Spliterator.SIZED | Spliterator.ORDERED);
Iterator<A> itrA = Spliterators.iterator(splitrA);
Iterator<B> itrB = Spliterators.iterator(splitrB);
return StreamSupport.stream(
new AbstractSpliterator<R>(
Math.min(splitrA.estimateSize(), splitrB.estimateSize()), characteristics) {
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (itrA.hasNext() && itrB.hasNext()) {
action.accept(function.apply(itrA.next(), itrB.next()));
return true;
}
return false;
}
},
isParallel)
.onClose(streamA::close)
.onClose(streamB::close);
}
Invokes consumer
once for each pair of corresponding elements in streamA
and streamB
. If one stream is longer than the other, the extra elements are silently ignored. Elements passed to the consumer are guaranteed to come from the same position in their respective source streams. For example:
Streams.forEachPair(
Stream.of("foo1", "foo2", "foo3"),
Stream.of("bar1", "bar2"),
(arg1, arg2) -> System.out.println(arg1 + ":" + arg2)
will print:
foo1:bar1
foo2:bar2
Warning: If either supplied stream is a parallel stream, the same correspondence
between elements will be made, but the order in which those pairs of elements are passed to the
consumer is not defined.
Note that many usages of this method can be replaced with simpler calls to zip
. This method behaves equivalently to zipping the stream elements into temporary pair objects and then using Stream.forEach
on that stream.
Since: 22.0
/**
* Invokes {@code consumer} once for each pair of <i>corresponding</i> elements in {@code streamA}
* and {@code streamB}. If one stream is longer than the other, the extra elements are silently
* ignored. Elements passed to the consumer are guaranteed to come from the same position in their
* respective source streams. For example:
*
* <pre>{@code
* Streams.forEachPair(
* Stream.of("foo1", "foo2", "foo3"),
* Stream.of("bar1", "bar2"),
* (arg1, arg2) -> System.out.println(arg1 + ":" + arg2)
* }</pre>
*
* <p>will print:
*
* <pre>{@code
* foo1:bar1
* foo2:bar2
* }</pre>
*
* <p><b>Warning:</b> If either supplied stream is a parallel stream, the same correspondence
* between elements will be made, but the order in which those pairs of elements are passed to the
* consumer is <i>not</i> defined.
*
* <p>Note that many usages of this method can be replaced with simpler calls to {@link #zip}.
* This method behaves equivalently to {@linkplain #zip zipping} the stream elements into
* temporary pair objects and then using {@link Stream#forEach} on that stream.
*
* @since 22.0
*/
public static <A, B> void forEachPair(
Stream<A> streamA, Stream<B> streamB, BiConsumer<? super A, ? super B> consumer) {
checkNotNull(consumer);
if (streamA.isParallel() || streamB.isParallel()) {
zip(streamA, streamB, TemporaryPair::new).forEach(pair -> consumer.accept(pair.a, pair.b));
} else {
Iterator<A> iterA = streamA.iterator();
Iterator<B> iterB = streamB.iterator();
while (iterA.hasNext() && iterB.hasNext()) {
consumer.accept(iterA.next(), iterB.next());
}
}
}
// Use this carefully - it doesn't implement value semantics
private static class TemporaryPair<A, B> {
final A a;
final B b;
TemporaryPair(A a, B b) {
this.a = a;
this.b = b;
}
}
Returns a stream consisting of the results of applying the given function to the elements of stream
and their indices in the stream. For example,
mapWithIndex(
Stream.of("a", "b", "c"),
(str, index) -> str + ":" + index)
would return Stream.of("a:0", "b:1", "c:2")
.
The resulting stream is efficiently splittable if and only if stream
was efficiently splittable and its underlying spliterator reported Spliterator.SUBSIZED
. This is generally the case if the underlying stream comes from a data structure supporting efficient indexed random access, typically an array or list.
The order of the resulting stream is defined if and only if the order of the original stream
was defined.
/**
* Returns a stream consisting of the results of applying the given function to the elements of
* {@code stream} and their indices in the stream. For example,
*
* <pre>{@code
* mapWithIndex(
* Stream.of("a", "b", "c"),
* (str, index) -> str + ":" + index)
* }</pre>
*
* <p>would return {@code Stream.of("a:0", "b:1", "c:2")}.
*
* <p>The resulting stream is <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* if and only if {@code stream} was efficiently splittable and its underlying spliterator
* reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream
* comes from a data structure supporting efficient indexed random access, typically an array or
* list.
*
* <p>The order of the resulting stream is defined if and only if the order of the original stream
* was defined.
*/
public static <T, R> Stream<R> mapWithIndex(
Stream<T> stream, FunctionWithIndex<? super T, ? extends R> function) {
checkNotNull(stream);
checkNotNull(function);
boolean isParallel = stream.isParallel();
Spliterator<T> fromSpliterator = stream.spliterator();
if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
Iterator<T> fromIterator = Spliterators.iterator(fromSpliterator);
return StreamSupport.stream(
new AbstractSpliterator<R>(
fromSpliterator.estimateSize(),
fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) {
long index = 0;
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromIterator.hasNext()) {
action.accept(function.apply(fromIterator.next(), index++));
return true;
}
return false;
}
},
isParallel)
.onClose(stream::close);
}
class Splitr extends MapWithIndexSpliterator<Spliterator<T>, R, Splitr> implements Consumer<T> {
@Nullable T holder;
Splitr(Spliterator<T> splitr, long index) {
super(splitr, index);
}
@Override
public void accept(@Nullable T t) {
this.holder = t;
}
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromSpliterator.tryAdvance(this)) {
try {
action.accept(function.apply(holder, index++));
return true;
} finally {
holder = null;
}
}
return false;
}
@Override
Splitr createSplit(Spliterator<T> from, long i) {
return new Splitr(from, i);
}
}
return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close);
}
Returns a stream consisting of the results of applying the given function to the elements of stream
and their indexes in the stream. For example,
mapWithIndex(
IntStream.of(0, 1, 2),
(i, index) -> i + ":" + index)
...would return Stream.of("0:0", "1:1", "2:2")
.
The resulting stream is efficiently splittable if and only if stream
was efficiently splittable and its underlying spliterator reported Spliterator.SUBSIZED
. This is generally the case if the underlying stream comes from a data structure supporting efficient indexed random access, typically an array or list.
The order of the resulting stream is defined if and only if the order of the original stream
was defined.
/**
* Returns a stream consisting of the results of applying the given function to the elements of
* {@code stream} and their indexes in the stream. For example,
*
* <pre>{@code
* mapWithIndex(
* IntStream.of(0, 1, 2),
* (i, index) -> i + ":" + index)
* }</pre>
*
* <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}.
*
* <p>The resulting stream is <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* if and only if {@code stream} was efficiently splittable and its underlying spliterator
* reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream
* comes from a data structure supporting efficient indexed random access, typically an array or
* list.
*
* <p>The order of the resulting stream is defined if and only if the order of the original stream
* was defined.
*/
public static <R> Stream<R> mapWithIndex(IntStream stream, IntFunctionWithIndex<R> function) {
checkNotNull(stream);
checkNotNull(function);
boolean isParallel = stream.isParallel();
Spliterator.OfInt fromSpliterator = stream.spliterator();
if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
PrimitiveIterator.OfInt fromIterator = Spliterators.iterator(fromSpliterator);
return StreamSupport.stream(
new AbstractSpliterator<R>(
fromSpliterator.estimateSize(),
fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) {
long index = 0;
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromIterator.hasNext()) {
action.accept(function.apply(fromIterator.nextInt(), index++));
return true;
}
return false;
}
},
isParallel)
.onClose(stream::close);
}
class Splitr extends MapWithIndexSpliterator<Spliterator.OfInt, R, Splitr>
implements IntConsumer, Spliterator<R> {
int holder;
Splitr(Spliterator.OfInt splitr, long index) {
super(splitr, index);
}
@Override
public void accept(int t) {
this.holder = t;
}
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromSpliterator.tryAdvance(this)) {
action.accept(function.apply(holder, index++));
return true;
}
return false;
}
@Override
Splitr createSplit(Spliterator.OfInt from, long i) {
return new Splitr(from, i);
}
}
return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close);
}
Returns a stream consisting of the results of applying the given function to the elements of stream
and their indexes in the stream. For example,
mapWithIndex(
LongStream.of(0, 1, 2),
(i, index) -> i + ":" + index)
...would return Stream.of("0:0", "1:1", "2:2")
.
The resulting stream is efficiently splittable if and only if stream
was efficiently splittable and its underlying spliterator reported Spliterator.SUBSIZED
. This is generally the case if the underlying stream comes from a data structure supporting efficient indexed random access, typically an array or list.
The order of the resulting stream is defined if and only if the order of the original stream
was defined.
/**
* Returns a stream consisting of the results of applying the given function to the elements of
* {@code stream} and their indexes in the stream. For example,
*
* <pre>{@code
* mapWithIndex(
* LongStream.of(0, 1, 2),
* (i, index) -> i + ":" + index)
* }</pre>
*
* <p>...would return {@code Stream.of("0:0", "1:1", "2:2")}.
*
* <p>The resulting stream is <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* if and only if {@code stream} was efficiently splittable and its underlying spliterator
* reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream
* comes from a data structure supporting efficient indexed random access, typically an array or
* list.
*
* <p>The order of the resulting stream is defined if and only if the order of the original stream
* was defined.
*/
public static <R> Stream<R> mapWithIndex(LongStream stream, LongFunctionWithIndex<R> function) {
checkNotNull(stream);
checkNotNull(function);
boolean isParallel = stream.isParallel();
Spliterator.OfLong fromSpliterator = stream.spliterator();
if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
PrimitiveIterator.OfLong fromIterator = Spliterators.iterator(fromSpliterator);
return StreamSupport.stream(
new AbstractSpliterator<R>(
fromSpliterator.estimateSize(),
fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) {
long index = 0;
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromIterator.hasNext()) {
action.accept(function.apply(fromIterator.nextLong(), index++));
return true;
}
return false;
}
},
isParallel)
.onClose(stream::close);
}
class Splitr extends MapWithIndexSpliterator<Spliterator.OfLong, R, Splitr>
implements LongConsumer, Spliterator<R> {
long holder;
Splitr(Spliterator.OfLong splitr, long index) {
super(splitr, index);
}
@Override
public void accept(long t) {
this.holder = t;
}
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromSpliterator.tryAdvance(this)) {
action.accept(function.apply(holder, index++));
return true;
}
return false;
}
@Override
Splitr createSplit(Spliterator.OfLong from, long i) {
return new Splitr(from, i);
}
}
return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close);
}
Returns a stream consisting of the results of applying the given function to the elements of stream
and their indexes in the stream. For example,
mapWithIndex(
DoubleStream.of(0, 1, 2),
(x, index) -> x + ":" + index)
...would return Stream.of("0.0:0", "1.0:1", "2.0:2")
.
The resulting stream is efficiently splittable if and only if stream
was efficiently splittable and its underlying spliterator reported Spliterator.SUBSIZED
. This is generally the case if the underlying stream comes from a data structure supporting efficient indexed random access, typically an array or list.
The order of the resulting stream is defined if and only if the order of the original stream
was defined.
/**
* Returns a stream consisting of the results of applying the given function to the elements of
* {@code stream} and their indexes in the stream. For example,
*
* <pre>{@code
* mapWithIndex(
* DoubleStream.of(0, 1, 2),
* (x, index) -> x + ":" + index)
* }</pre>
*
* <p>...would return {@code Stream.of("0.0:0", "1.0:1", "2.0:2")}.
*
* <p>The resulting stream is <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* if and only if {@code stream} was efficiently splittable and its underlying spliterator
* reported {@link Spliterator#SUBSIZED}. This is generally the case if the underlying stream
* comes from a data structure supporting efficient indexed random access, typically an array or
* list.
*
* <p>The order of the resulting stream is defined if and only if the order of the original stream
* was defined.
*/
public static <R> Stream<R> mapWithIndex(
DoubleStream stream, DoubleFunctionWithIndex<R> function) {
checkNotNull(stream);
checkNotNull(function);
boolean isParallel = stream.isParallel();
Spliterator.OfDouble fromSpliterator = stream.spliterator();
if (!fromSpliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
PrimitiveIterator.OfDouble fromIterator = Spliterators.iterator(fromSpliterator);
return StreamSupport.stream(
new AbstractSpliterator<R>(
fromSpliterator.estimateSize(),
fromSpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) {
long index = 0;
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromIterator.hasNext()) {
action.accept(function.apply(fromIterator.nextDouble(), index++));
return true;
}
return false;
}
},
isParallel)
.onClose(stream::close);
}
class Splitr extends MapWithIndexSpliterator<Spliterator.OfDouble, R, Splitr>
implements DoubleConsumer, Spliterator<R> {
double holder;
Splitr(Spliterator.OfDouble splitr, long index) {
super(splitr, index);
}
@Override
public void accept(double t) {
this.holder = t;
}
@Override
public boolean tryAdvance(Consumer<? super R> action) {
if (fromSpliterator.tryAdvance(this)) {
action.accept(function.apply(holder, index++));
return true;
}
return false;
}
@Override
Splitr createSplit(Spliterator.OfDouble from, long i) {
return new Splitr(from, i);
}
}
return StreamSupport.stream(new Splitr(fromSpliterator, 0), isParallel).onClose(stream::close);
}
An analogue of Function
also accepting an index. This interface is only intended for use by callers of Streams.mapWithIndex(Stream<Object>, FunctionWithIndex<? super Object,? extends Object>)
.
Since: 21.0
/**
* An analogue of {@link java.util.function.Function} also accepting an index.
*
* <p>This interface is only intended for use by callers of {@link #mapWithIndex(Stream,
* FunctionWithIndex)}.
*
* @since 21.0
*/
@Beta
public interface FunctionWithIndex<T, R> {
Applies this function to the given argument and its index within a stream. /** Applies this function to the given argument and its index within a stream. */
R apply(T from, long index);
}
private abstract static class MapWithIndexSpliterator<
F extends Spliterator<?>, R, S extends MapWithIndexSpliterator<F, R, S>>
implements Spliterator<R> {
final F fromSpliterator;
long index;
MapWithIndexSpliterator(F fromSpliterator, long index) {
this.fromSpliterator = fromSpliterator;
this.index = index;
}
abstract S createSplit(F from, long i);
@Override
public S trySplit() {
@SuppressWarnings("unchecked")
F split = (F) fromSpliterator.trySplit();
if (split == null) {
return null;
}
S result = createSplit(split, index);
this.index += split.getExactSizeIfKnown();
return result;
}
@Override
public long estimateSize() {
return fromSpliterator.estimateSize();
}
@Override
public int characteristics() {
return fromSpliterator.characteristics()
& (Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED);
}
}
An analogue of IntFunction
also accepting an index. This interface is only intended for use by callers of Streams.mapWithIndex(IntStream, IntFunctionWithIndex<Object>)
.
Since: 21.0
/**
* An analogue of {@link java.util.function.IntFunction} also accepting an index.
*
* <p>This interface is only intended for use by callers of {@link #mapWithIndex(IntStream,
* IntFunctionWithIndex)}.
*
* @since 21.0
*/
@Beta
public interface IntFunctionWithIndex<R> {
Applies this function to the given argument and its index within a stream. /** Applies this function to the given argument and its index within a stream. */
R apply(int from, long index);
}
An analogue of LongFunction
also accepting an index. This interface is only intended for use by callers of Streams.mapWithIndex(LongStream, LongFunctionWithIndex<Object>)
.
Since: 21.0
/**
* An analogue of {@link java.util.function.LongFunction} also accepting an index.
*
* <p>This interface is only intended for use by callers of {@link #mapWithIndex(LongStream,
* LongFunctionWithIndex)}.
*
* @since 21.0
*/
@Beta
public interface LongFunctionWithIndex<R> {
Applies this function to the given argument and its index within a stream. /** Applies this function to the given argument and its index within a stream. */
R apply(long from, long index);
}
An analogue of DoubleFunction
also accepting an index. This interface is only intended for use by callers of Streams.mapWithIndex(DoubleStream, DoubleFunctionWithIndex<Object>)
.
Since: 21.0
/**
* An analogue of {@link java.util.function.DoubleFunction} also accepting an index.
*
* <p>This interface is only intended for use by callers of {@link #mapWithIndex(DoubleStream,
* DoubleFunctionWithIndex)}.
*
* @since 21.0
*/
@Beta
public interface DoubleFunctionWithIndex<R> {
Applies this function to the given argument and its index within a stream. /** Applies this function to the given argument and its index within a stream. */
R apply(double from, long index);
}
Returns the last element of the specified stream, or Optional.empty
if the stream is empty. Equivalent to stream.reduce((a, b) -> b)
, but may perform significantly better. This method's runtime will be between O(log n) and O(n), performing better on efficiently splittable
streams.
If the stream has nondeterministic order, this has equivalent semantics to Stream.findAny
(which you might as well use).
Throws: - NullPointerException – if the last element of the stream is null
See Also:
/**
* Returns the last element of the specified stream, or {@link java.util.Optional#empty} if the
* stream is empty.
*
* <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This
* method's runtime will be between O(log n) and O(n), performing better on <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* streams.
*
* <p>If the stream has nondeterministic order, this has equivalent semantics to {@link
* Stream#findAny} (which you might as well use).
*
* @see Stream#findFirst()
* @throws NullPointerException if the last element of the stream is null
*/
public static <T> java.util.Optional<T> findLast(Stream<T> stream) {
class OptionalState {
boolean set = false;
T value = null;
void set(@Nullable T value) {
this.set = true;
this.value = value;
}
T get() {
checkState(set);
return value;
}
}
OptionalState state = new OptionalState();
Deque<Spliterator<T>> splits = new ArrayDeque<>();
splits.addLast(stream.spliterator());
while (!splits.isEmpty()) {
Spliterator<T> spliterator = splits.removeLast();
if (spliterator.getExactSizeIfKnown() == 0) {
continue; // drop this split
}
// Many spliterators will have trySplits that are SUBSIZED even if they are not themselves
// SUBSIZED.
if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
// we can drill down to exactly the smallest nonempty spliterator
while (true) {
Spliterator<T> prefix = spliterator.trySplit();
if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
break;
} else if (spliterator.getExactSizeIfKnown() == 0) {
spliterator = prefix;
break;
}
}
// spliterator is known to be nonempty now
spliterator.forEachRemaining(state::set);
return java.util.Optional.of(state.get());
}
Spliterator<T> prefix = spliterator.trySplit();
if (prefix == null || prefix.getExactSizeIfKnown() == 0) {
// we can't split this any further
spliterator.forEachRemaining(state::set);
if (state.set) {
return java.util.Optional.of(state.get());
}
// fall back to the last split
continue;
}
splits.addLast(prefix);
splits.addLast(spliterator);
}
return java.util.Optional.empty();
}
Returns the last element of the specified stream, or OptionalInt.empty
if the stream is empty. Equivalent to stream.reduce((a, b) -> b)
, but may perform significantly better. This method's runtime will be between O(log n) and O(n), performing better on efficiently splittable
streams.
Throws: - NullPointerException – if the last element of the stream is null
See Also:
/**
* Returns the last element of the specified stream, or {@link OptionalInt#empty} if the stream is
* empty.
*
* <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This
* method's runtime will be between O(log n) and O(n), performing better on <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* streams.
*
* @see IntStream#findFirst()
* @throws NullPointerException if the last element of the stream is null
*/
public static OptionalInt findLast(IntStream stream) {
// findLast(Stream) does some allocation, so we might as well box some more
java.util.Optional<Integer> boxedLast = findLast(stream.boxed());
return boxedLast.isPresent() ? OptionalInt.of(boxedLast.get()) : OptionalInt.empty();
}
Returns the last element of the specified stream, or OptionalLong.empty
if the stream is empty. Equivalent to stream.reduce((a, b) -> b)
, but may perform significantly better. This method's runtime will be between O(log n) and O(n), performing better on efficiently splittable
streams.
Throws: - NullPointerException – if the last element of the stream is null
See Also:
/**
* Returns the last element of the specified stream, or {@link OptionalLong#empty} if the stream
* is empty.
*
* <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This
* method's runtime will be between O(log n) and O(n), performing better on <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* streams.
*
* @see LongStream#findFirst()
* @throws NullPointerException if the last element of the stream is null
*/
public static OptionalLong findLast(LongStream stream) {
// findLast(Stream) does some allocation, so we might as well box some more
java.util.Optional<Long> boxedLast = findLast(stream.boxed());
return boxedLast.isPresent() ? OptionalLong.of(boxedLast.get()) : OptionalLong.empty();
}
Returns the last element of the specified stream, or OptionalDouble.empty
if the stream is empty. Equivalent to stream.reduce((a, b) -> b)
, but may perform significantly better. This method's runtime will be between O(log n) and O(n), performing better on efficiently splittable
streams.
Throws: - NullPointerException – if the last element of the stream is null
See Also:
/**
* Returns the last element of the specified stream, or {@link OptionalDouble#empty} if the stream
* is empty.
*
* <p>Equivalent to {@code stream.reduce((a, b) -> b)}, but may perform significantly better. This
* method's runtime will be between O(log n) and O(n), performing better on <a
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>
* streams.
*
* @see DoubleStream#findFirst()
* @throws NullPointerException if the last element of the stream is null
*/
public static OptionalDouble findLast(DoubleStream stream) {
// findLast(Stream) does some allocation, so we might as well box some more
java.util.Optional<Double> boxedLast = findLast(stream.boxed());
return boxedLast.isPresent() ? OptionalDouble.of(boxedLast.get()) : OptionalDouble.empty();
}
private Streams() {}
}