/*
* Copyright 2015, 2016 Tagir Valeev
*
* 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 one.util.streamex;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.function.*;
import java.util.stream.*;
import java.util.stream.Collector.Characteristics;
import static one.util.streamex.StreamExInternals.*;
/**
* Base class providing common functionality for {@link StreamEx} and {@link EntryStream}.
*
* @author Tagir Valeev
*
* @param <T> the type of the stream elements
* @param <S> the type of of the stream extending {@code AbstractStreamEx}
*/
public abstract class AbstractStreamEx<T, S extends AbstractStreamEx<T, S>> extends
BaseStreamEx<T, Stream<T>, Spliterator<T>, S> implements Stream<T>, Iterable<T> {
@SuppressWarnings("unchecked")
AbstractStreamEx(Stream<? extends T> stream, StreamContext context) {
super((Stream<T>)stream, context);
}
@SuppressWarnings("unchecked")
AbstractStreamEx(Spliterator<? extends T> spliterator, StreamContext context) {
super((Spliterator<T>)spliterator, context);
}
@Override
final Stream<T> createStream() {
return StreamSupport.stream(spliterator, context.parallel);
}
final <K, V, M extends Map<K, V>> M toMapThrowing(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valMapper, M map) {
forEach(t -> addToMap(map, keyMapper.apply(t), Objects.requireNonNull(valMapper.apply(t))));
return map;
}
final <K, V, M extends Map<K, V>> void addToMap(M map, K key, V val) {
V oldVal = map.putIfAbsent(key, val);
if (oldVal != null) {
throw new IllegalStateException("Duplicate entry for key '" + key + "' (attempt to merge values '" + oldVal
+ "' and '" + val + "')");
}
}
<R, A> R rawCollect(Collector<? super T, A, R> collector) {
if (context.fjp != null)
return context.terminate(collector, stream()::collect);
return stream().collect(collector);
}
@SuppressWarnings("unchecked")
S appendSpliterator(Stream<? extends T> other, Spliterator<? extends T> right) {
if (right.getExactSizeIfKnown() == 0)
return (S) this;
Spliterator<T> left = spliterator();
Spliterator<T> result;
if (left.getExactSizeIfKnown() == 0)
result = (Spliterator<T>) right;
else
result = new TailConcatSpliterator<>(left, right);
context = context.combine(other);
return supply(result);
}
@SuppressWarnings("unchecked")
S prependSpliterator(Stream<? extends T> other, Spliterator<? extends T> left) {
if (left.getExactSizeIfKnown() == 0)
return (S) this;
Spliterator<T> right = spliterator();
Spliterator<T> result;
if (right.getExactSizeIfKnown() == 0)
result = (Spliterator<T>) left;
else
result = new TailConcatSpliterator<>(left, right);
context = context.combine(other);
return supply(result);
}
abstract S supply(Stream<T> stream);
abstract S supply(Spliterator<T> spliterator);
@Override
public Iterator<T> iterator() {
return Spliterators.iterator(spliterator());
}
@SuppressWarnings("unchecked")
@Override
public S sequential() {
return (S) super.sequential();
}
@SuppressWarnings("unchecked")
@Override
public S parallel() {
return (S) super.parallel();
}
@Override
@SuppressWarnings("unchecked")
public S parallel(ForkJoinPool fjp) {
return (S) super.parallel(fjp);
}
@SuppressWarnings("unchecked")
@Override
public S unordered() {
return (S) super.unordered();
}
@SuppressWarnings("unchecked")
@Override
public S onClose(Runnable closeHandler) {
return (S) super.onClose(closeHandler);
}
@Override
public S filter(Predicate<? super T> predicate) {
return supply(stream().filter(predicate));
}
@Override
public <R> StreamEx<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
return new StreamEx<>(stream().flatMap(mapper), context);
}
@Override
public <R> StreamEx<R> map(Function<? super T, ? extends R> mapper) {
return new StreamEx<>(stream().map(mapper), context);
}
@Override
public IntStreamEx mapToInt(ToIntFunction<? super T> mapper) {
return new IntStreamEx(stream().mapToInt(mapper), context);
}
@Override
public LongStreamEx mapToLong(ToLongFunction<? super T> mapper) {
return new LongStreamEx(stream().mapToLong(mapper), context);
}
@Override
public DoubleStreamEx mapToDouble(ToDoubleFunction<? super T> mapper) {
return new DoubleStreamEx(stream().mapToDouble(mapper), context);
}
@Override
public IntStreamEx flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
return new IntStreamEx(stream().flatMapToInt(mapper), context);
}
@Override
public LongStreamEx flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
return new LongStreamEx(stream().flatMapToLong(mapper), context);
}
@Override
public DoubleStreamEx flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
return new DoubleStreamEx(stream().flatMapToDouble(mapper), context);
}
/**
* Returns a new stream containing all the elements of the original stream interspersed with
* given delimiter.
*
* <p>
* For example, {@code StreamEx.of("a", "b", "c").intersperse("x")} will yield a stream containing
* five elements: a, x, b, x, c.
*
* <p>
* This is an <a href="package-summary.html#StreamOps">intermediate operation</a>.
*
* @param delimiter a delimiter to be inserted between each pair of elements
* @return the new stream
* @since 0.6.6
*/
public S intersperse(T delimiter) {
return supply(stream().flatMap(s -> StreamEx.of(delimiter, s)).skip(1));
}
@Override
public S distinct() {
return supply(stream().distinct());
}
/**
* Returns a stream consisting of the distinct elements of this stream
* (according to object equality of the results of applying the given
* function).
*
* <p>
* For ordered streams, the selection of distinct elements is stable (for
* duplicated elements, the element appearing first in the encounter order
* is preserved.) For unordered streams, no stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param keyExtractor a non-interfering, stateless function which
* classifies input elements.
* @return the new stream
* @since 0.3.8
*/
public S distinct(Function<? super T, ?> keyExtractor) {
return supply(stream().map(t -> new PairBox<>(t, keyExtractor.apply(t))).distinct().map(box -> box.a));
}
@Override
public S sorted() {
return supply(stream().sorted());
}
@Override
public S sorted(Comparator<? super T> comparator) {
return supply(stream().sorted(comparator));
}
@Override
public S peek(Consumer<? super T> action) {
return supply(stream().peek(action));
}
@Override
public S limit(long maxSize) {
return supply(stream().limit(maxSize));
}
@Override
public S skip(long n) {
return supply(stream().skip(n));
}
@Override
public void forEach(Consumer<? super T> action) {
if (spliterator != null && !isParallel()) {
spliterator().forEachRemaining(action);
} else {
if (context.fjp != null)
context.terminate(() -> {
stream().forEach(action);
return null;
});
else {
stream().forEach(action);
}
}
}
@Override
public void forEachOrdered(Consumer<? super T> action) {
if (spliterator != null && !isParallel()) {
spliterator().forEachRemaining(action);
} else {
if (context.fjp != null)
context.terminate(() -> {
stream().forEachOrdered(action);
return null;
});
else {
stream().forEachOrdered(action);
}
}
}
@Override
public Object[] toArray() {
return toArray(Object[]::new);
}
@Override
public <A> A[] toArray(IntFunction<A[]> generator) {
if (context.fjp != null)
return context.terminate(generator, stream()::toArray);
return stream().toArray(generator);
}
@Override
public T reduce(T identity, BinaryOperator<T> accumulator) {
if (context.fjp != null)
return context.terminate(() -> stream().reduce(identity, accumulator));
return stream().reduce(identity, accumulator);
}
@Override
public Optional<T> reduce(BinaryOperator<T> accumulator) {
if (context.fjp != null)
return context.terminate(accumulator, stream()::reduce);
return stream().reduce(accumulator);
}
@Override
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
if (context.fjp != null)
return context.terminate(() -> stream().reduce(identity, accumulator, combiner));
return stream().reduce(identity, accumulator, combiner);
}
@Override
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
if (context.fjp != null)
return context.terminate(() -> stream().collect(supplier, accumulator, combiner));
return stream().collect(supplier, accumulator, combiner);
}
/**
* {@inheritDoc}
*
* <p>
* If special <a
* href="package-summary.html#ShortCircuitReduction">short-circuiting
* collector</a> is passed, this operation becomes short-circuiting as well.
*/
@Override
public <R, A> R collect(Collector<? super T, A, R> collector) {
Predicate<A> finished = finished(collector);
if (finished != null) {
BiConsumer<A, ? super T> acc = collector.accumulator();
BinaryOperator<A> combiner = collector.combiner();
Spliterator<T> spliterator = spliterator();
if (!isParallel()) {
A a = collector.supplier().get();
if (!finished.test(a)) {
try {
// forEachRemaining can be much faster
// and take much less memory than tryAdvance for certain
// spliterators
spliterator.forEachRemaining(e -> {
acc.accept(a, e);
if (finished.test(a))
throw new CancelException();
});
} catch (CancelException ex) {
// ignore
}
}
return collector.finisher().apply(a);
}
Spliterator<A> spltr;
if (!spliterator.hasCharacteristics(Spliterator.ORDERED)
|| collector.characteristics().contains(Characteristics.UNORDERED)) {
spltr = new UnorderedCancellableSpliterator<>(spliterator, collector.supplier(), acc, combiner,
finished);
} else {
spltr = new OrderedCancellableSpliterator<>(spliterator, collector.supplier(), acc, combiner, finished);
}
return collector.finisher().apply(
new StreamEx<>(StreamSupport.stream(spltr, true), context).findFirst().get());
}
return rawCollect(collector);
}
@Override
public Optional<T> min(Comparator<? super T> comparator) {
return reduce(BinaryOperator.minBy(comparator));
}
@Override
public Optional<T> max(Comparator<? super T> comparator) {
return reduce(BinaryOperator.maxBy(comparator));
}
@Override
public long count() {
if (context.fjp != null)
return context.terminate(stream()::count);
return stream().count();
}
@Override
public boolean anyMatch(Predicate<? super T> predicate) {
if (context.fjp != null)
return context.terminate(predicate, stream()::anyMatch);
return stream().anyMatch(predicate);
}
@Override
public boolean allMatch(Predicate<? super T> predicate) {
if (context.fjp != null)
return context.terminate(predicate, stream()::allMatch);
return stream().allMatch(predicate);
}
@Override
public boolean noneMatch(Predicate<? super T> predicate) {
return !anyMatch(predicate);
}
@Override
public Optional<T> findFirst() {
if (context.fjp != null)
return context.terminate(stream()::findFirst);
return stream().findFirst();
}
@Override
public Optional<T> findAny() {
if (context.fjp != null)
return context.terminate(stream()::findAny);
return stream().findAny();
}
/**
* Returns an {@link OptionalLong} describing the zero-based index of the
* first element of this stream, which equals to the given element, or an
* empty {@code OptionalLong} if there's no matching element.
*
* <p>
* This is a short-circuiting terminal operation.
*
* @param element an element to look for
* @return an {@code OptionalLong} describing the index of the first
* matching element of this stream, or an empty {@code OptionalLong}
* if there's no matching element.
* @see #indexOf(Predicate)
* @since 0.4.0
*/
public OptionalLong indexOf(T element) {
return indexOf(Predicate.isEqual(element));
}
/**
* Returns an {@link OptionalLong} describing the zero-based index of the
* first element of this stream, which matches given predicate, or an empty
* {@code OptionalLong} if there's no matching element.
*
* <p>
* This is a short-circuiting terminal operation.
*
* @param predicate a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate which returned value should match
* @return an {@code OptionalLong} describing the index of the first
* matching element of this stream, or an empty {@code OptionalLong}
* if there's no matching element.
* @see #findFirst(Predicate)
* @see #indexOf(Object)
* @since 0.4.0
*/
public OptionalLong indexOf(Predicate<? super T> predicate) {
return collect(new CancellableCollectorImpl<T, long[], OptionalLong>(() -> new long[] { -1 }, (acc, t) -> {
if (acc[0] < 0) {
if (predicate.test(t)) {
acc[0] = -acc[0] - 1;
} else {
acc[0]--;
}
}
}, (acc1, acc2) -> {
if (acc1[0] < 0) {
if (acc2[0] < 0) {
acc1[0] = acc1[0] + acc2[0] + 1;
} else {
acc1[0] = acc2[0] - acc1[0] - 1;
}
}
return acc1;
}, acc -> acc[0] < 0 ? OptionalLong.empty() : OptionalLong.of(acc[0]), acc -> acc[0] >= 0, NO_CHARACTERISTICS));
}
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of a mapped collection produced by applying
* the provided mapping function to each element. (If a mapped collection is
* {@code null} nothing is added for given element to the resulting stream.)
*
* <p>
* This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* <p>
* The {@code flatCollection()} operation has the effect of applying a
* one-to-many transformation to the elements of the stream, and then
* flattening the resulting elements into a new stream.
*
* @param <R> The element type of the new stream
* @param mapper a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to apply to each element which produces a
* {@link Collection} of new values
* @return the new stream
*/
public <R> StreamEx<R> flatCollection(Function<? super T, ? extends Collection<? extends R>> mapper) {
return flatMap(t -> {
Collection<? extends R> c = mapper.apply(t);
return c == null ? null : StreamEx.of(c.spliterator());
});
}
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of a mapped array produced by applying
* the provided mapping function to each element. (If a mapped array is
* {@code null} nothing is added for given element to the resulting stream.)
*
* <p>
* This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* <p>
* The {@code flatArray()} operation has the effect of applying a
* one-to-many transformation to the elements of the stream, and then
* flattening the resulting elements into a new stream.
*
* @param <R> The element type of the new stream
* @param mapper a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to apply to each element which produces an
* array of new values
* @return the new stream
* @since 0.6.5
*/
public <R> StreamEx<R> flatArray(Function<? super T, ? extends R[]> mapper) {
return flatMap(t -> {
R[] a = mapper.apply(t);
return a == null ? null : StreamEx.of(Arrays.spliterator(a));
});
}
/**
* Returns a stream consisting of the elements of this stream that don't
* match the given predicate.
*
* <p>
* This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* @param predicate a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to each element to determine if it should be
* excluded
* @return the new stream
*/
public S remove(Predicate<? super T> predicate) {
return filter(predicate.negate());
}
/**
* Returns a stream consisting of the elements of this stream that aren't
* null.
*
* <p>
* This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* @return the new stream
*/
public S nonNull() {
return filter(Objects::nonNull);
}
/**
* Returns an {@link Optional} describing some element of the stream, which
* matches given predicate, or an empty {@code Optional} if there's no
* matching element.
*
* <p>
* This is a short-circuiting terminal operation.
*
* <p>
* The behavior of this operation is explicitly nondeterministic; it is free
* to select any element in the stream. This is to allow for maximal
* performance in parallel operations; the cost is that multiple invocations
* on the same source may not return the same result. (If a stable result is
* desired, use {@link #findFirst(Predicate)} instead.)
*
* @param predicate a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate which returned value should match
* @return an {@code Optional} describing some matching element of this
* stream, or an empty {@code Optional} if there's no matching
* element
* @throws NullPointerException if the element selected is null
* @see #findAny()
* @see #findFirst(Predicate)
*/
public Optional<T> findAny(Predicate<? super T> predicate) {
return filter(predicate).findAny();
}
/**
* Returns an {@link Optional} describing the first element of this stream,
* which matches given predicate, or an empty {@code Optional} if there's no
* matching element.
*
* <p>
* This is a short-circuiting terminal operation.
*
* @param predicate a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate which returned value should match
* @return an {@code Optional} describing the first matching element of this
* stream, or an empty {@code Optional} if there's no matching
* element
* @throws NullPointerException if the element selected is null
* @see #findFirst()
*/
public Optional<T> findFirst(Predicate<? super T> predicate) {
return filter(predicate).findFirst();
}
/**
* Returns a stream consisting of the elements of this stream, sorted in
* descending order according to the provided {@code Comparator}.
*
* <p>
* For ordered streams, the sort is stable. For unordered streams, no
* stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param comparator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* {@code Comparator} to be used to compare stream elements
* @return the new stream
*/
public S reverseSorted(Comparator<? super T> comparator) {
return sorted(comparator.reversed());
}
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the natural order of the keys extracted by provided
* function.
*
* <p>
* For ordered streams, the sort is stable. For unordered streams, no
* stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param <V> the type of the {@code Comparable} sort key
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to be used to extract sorting keys
* @return the new stream
*/
public <V extends Comparable<? super V>> S sortedBy(Function<? super T, ? extends V> keyExtractor) {
return sorted(Comparator.comparing(keyExtractor));
}
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the int values extracted by provided function.
*
* <p>
* For ordered streams, the sort is stable. For unordered streams, no
* stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to be used to extract sorting keys
* @return the new stream
*/
public S sortedByInt(ToIntFunction<? super T> keyExtractor) {
return sorted(Comparator.comparingInt(keyExtractor));
}
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the long values extracted by provided function.
*
* <p>
* For ordered streams, the sort is stable. For unordered streams, no
* stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to be used to extract sorting keys
* @return the new stream
*/
public S sortedByLong(ToLongFunction<? super T> keyExtractor) {
return sorted(Comparator.comparingLong(keyExtractor));
}
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the double values extracted by provided function.
*
* <p>
* For ordered streams, the sort is stable. For unordered streams, no
* stability guarantees are made.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">stateful intermediate
* operation</a>.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to be used to extract sorting keys
* @return the new stream
*/
public S sortedByDouble(ToDoubleFunction<? super T> keyExtractor) {
return sorted(Comparator.comparingDouble(keyExtractor));
}
/**
* Returns the minimum element of this stream according to the natural order
* of the keys extracted by provided function. This is a special case of a
* reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparing(keyExtractor))}, but may work faster as
* keyExtractor function is applied only once per each input element.
*
* @param <V> the type of the comparable keys
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the comparable keys from this stream elements
* @return an {@code Optional} describing the minimum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the minimum element is null
*/
public <V extends Comparable<? super V>> Optional<T> minBy(Function<? super T, ? extends V> keyExtractor) {
return Box
.asOptional(reduce(null, (PairBox<T, V> acc, T t) -> {
V val = keyExtractor.apply(t);
if (acc == null)
return new PairBox<>(t, val);
if (val.compareTo(acc.b) < 0) {
acc.b = val;
acc.a = t;
}
return acc;
}, (PairBox<T, V> acc1, PairBox<T, V> acc2) -> (acc1 == null || acc2 != null
&& acc1.b.compareTo(acc2.b) > 0) ? acc2 : acc1));
}
/**
* Returns the minimum element of this stream according to the int values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingInt(keyExtractor))}, but may work faster
* as keyExtractor function is applied only once per each input element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the int keys from this stream elements
* @return an {@code Optional} describing the minimum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the minimum element is null
*/
public Optional<T> minByInt(ToIntFunction<? super T> keyExtractor) {
return Box.asOptional(reduce(null, (ObjIntBox<T> acc, T t) -> {
int val = keyExtractor.applyAsInt(t);
if (acc == null)
return new ObjIntBox<>(t, val);
if (val < acc.b) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjIntBox<T> acc1, ObjIntBox<T> acc2) -> (acc1 == null || acc2 != null && acc1.b > acc2.b) ? acc2 : acc1));
}
/**
* Returns the minimum element of this stream according to the long values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingLong(keyExtractor))}, but may work faster
* as keyExtractor function is applied only once per each input element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the long keys from this stream elements
* @return an {@code Optional} describing the minimum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the minimum element is null
*/
public Optional<T> minByLong(ToLongFunction<? super T> keyExtractor) {
return Box
.asOptional(reduce(null, (ObjLongBox<T> acc, T t) -> {
long val = keyExtractor.applyAsLong(t);
if (acc == null)
return new ObjLongBox<>(t, val);
if (val < acc.b) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjLongBox<T> acc1, ObjLongBox<T> acc2) -> (acc1 == null || acc2 != null && acc1.b > acc2.b) ? acc2
: acc1));
}
/**
* Returns the minimum element of this stream according to the double values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingDouble(keyExtractor))}, but may work
* faster as keyExtractor function is applied only once per each input
* element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the double keys from this stream elements
* @return an {@code Optional} describing the minimum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the minimum element is null
*/
public Optional<T> minByDouble(ToDoubleFunction<? super T> keyExtractor) {
return Box.asOptional(reduce(null, (ObjDoubleBox<T> acc, T t) -> {
double val = keyExtractor.applyAsDouble(t);
if (acc == null)
return new ObjDoubleBox<>(t, val);
if (Double.compare(val, acc.b) < 0) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjDoubleBox<T> acc1, ObjDoubleBox<T> acc2) -> (acc1 == null || acc2 != null
&& Double.compare(acc1.b, acc2.b) > 0) ? acc2 : acc1));
}
/**
* Returns the maximum element of this stream according to the natural order
* of the keys extracted by provided function. This is a special case of a
* reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparing(keyExtractor))}, but may work faster as
* keyExtractor function is applied only once per each input element.
*
* @param <V> the type of the comparable keys
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the comparable keys from this stream elements
* @return an {@code Optional} describing the maximum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the maximum element is null
*/
public <V extends Comparable<? super V>> Optional<T> maxBy(Function<? super T, ? extends V> keyExtractor) {
return Box
.asOptional(reduce(null, (PairBox<T, V> acc, T t) -> {
V val = keyExtractor.apply(t);
if (acc == null)
return new PairBox<>(t, val);
if (val.compareTo(acc.b) > 0) {
acc.b = val;
acc.a = t;
}
return acc;
}, (PairBox<T, V> acc1, PairBox<T, V> acc2) -> (acc1 == null || acc2 != null
&& acc1.b.compareTo(acc2.b) < 0) ? acc2 : acc1));
}
/**
* Returns the maximum element of this stream according to the int values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingInt(keyExtractor))}, but may work faster
* as keyExtractor function is applied only once per each input element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the int keys from this stream elements
* @return an {@code Optional} describing the maximum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the maximum element is null
*/
public Optional<T> maxByInt(ToIntFunction<? super T> keyExtractor) {
return Box.asOptional(reduce(null, (ObjIntBox<T> acc, T t) -> {
int val = keyExtractor.applyAsInt(t);
if (acc == null)
return new ObjIntBox<>(t, val);
if (val > acc.b) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjIntBox<T> acc1, ObjIntBox<T> acc2) -> (acc1 == null || acc2 != null && acc1.b < acc2.b) ? acc2 : acc1));
}
/**
* Returns the maximum element of this stream according to the long values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingLong(keyExtractor))}, but may work faster
* as keyExtractor function is applied only once per each input element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the long keys from this stream elements
* @return an {@code Optional} describing the maximum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the maximum element is null
*/
public Optional<T> maxByLong(ToLongFunction<? super T> keyExtractor) {
return Box
.asOptional(reduce(null, (ObjLongBox<T> acc, T t) -> {
long val = keyExtractor.applyAsLong(t);
if (acc == null)
return new ObjLongBox<>(t, val);
if (val > acc.b) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjLongBox<T> acc1, ObjLongBox<T> acc2) -> (acc1 == null || acc2 != null && acc1.b < acc2.b) ? acc2
: acc1));
}
/**
* Returns the maximum element of this stream according to the double values
* extracted by provided function. This is a special case of a reduction.
*
* <p>
* This is a terminal operation.
*
* <p>
* This method is equivalent to
* {@code min(Comparator.comparingDouble(keyExtractor))}, but may work
* faster as keyExtractor function is applied only once per each input
* element.
*
* @param keyExtractor a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function to extract the double keys from this stream elements
* @return an {@code Optional} describing the maximum element of this
* stream, or an empty {@code Optional} if the stream is empty
* @throws NullPointerException if the maximum element is null
*/
public Optional<T> maxByDouble(ToDoubleFunction<? super T> keyExtractor) {
return Box.asOptional(reduce(null, (ObjDoubleBox<T> acc, T t) -> {
double val = keyExtractor.applyAsDouble(t);
if (acc == null)
return new ObjDoubleBox<>(t, val);
if (Double.compare(val, acc.b) > 0) {
acc.b = val;
acc.a = t;
}
return acc;
}, (ObjDoubleBox<T> acc1, ObjDoubleBox<T> acc2) -> (acc1 == null || acc2 != null
&& Double.compare(acc1.b, acc2.b) < 0) ? acc2 : acc1));
}
/**
* Creates a lazily concatenated stream whose elements are all the elements
* of this stream followed by all the elements of the other stream. The
* resulting stream is ordered if both of the input streams are ordered, and
* parallel if either of the input streams is parallel. When the resulting
* stream is closed, the close handlers for both input streams are invoked.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">quasi-intermediate
* operation</a> with <a href="package-summary.html#TSO">tail-stream
* optimization</a>.
*
* <p>
* May return this if the supplied stream is known to be empty.
*
* @param other the other stream
* @return this stream appended by the other stream
* @see Stream#concat(Stream, Stream)
*/
public S append(Stream<? extends T> other) {
return appendSpliterator(other, other.spliterator());
}
/**
* Creates a lazily concatenated stream whose elements are all the elements
* of the other stream followed by all the elements of this stream. The
* resulting stream is ordered if both of the input streams are ordered, and
* parallel if either of the input streams is parallel. When the resulting
* stream is closed, the close handlers for both input streams are invoked.
*
* <p>
* This is a <a href="package-summary.html#StreamOps">quasi-intermediate
* operation</a> with <a href="package-summary.html#TSO">tail-stream
* optimization</a>.
*
* <p>
* May return this if the supplied stream is known to be empty.
*
* @param other the other stream
* @return this stream prepended by the other stream
* @see Stream#concat(Stream, Stream)
*/
public S prepend(Stream<? extends T> other) {
return prependSpliterator(other, other.spliterator());
}
/**
* Returns a {@link List} containing the elements of this stream. The
* returned {@code List} is guaranteed to be mutable, but there are no
* guarantees on the type, serializability, or thread-safety; if more
* control over the returned {@code List} is required, use
* {@link #toCollection(Supplier)}.
*
* <p>
* This is a terminal operation.
*
* @return a {@code List} containing the elements of this stream
* @see Collectors#toList()
* @see #toImmutableList()
*/
@SuppressWarnings("unchecked")
public List<T> toList() {
return new ArrayList<>((Collection<T>) new ArrayCollection(toArray(Object[]::new)));
}
/**
* Returns an immutable {@link List} containing the elements of this stream.
* There's no guarantees on exact type of the returned {@code List}. The
* returned {@code List} is guaranteed to be serializable if all its
* elements are serializable.
*
* <p>
* This is a terminal operation.
*
* @return a {@code List} containing the elements of this stream
* @see #toList()
* @since 0.6.3
*/
@SuppressWarnings("unchecked")
public List<T> toImmutableList() {
Object[] array = toArray(Object[]::new);
switch(array.length) {
case 0:
return Collections.emptyList();
case 1:
return Collections.singletonList((T) array[0]);
default:
return Collections.unmodifiableList(Arrays.asList((T[]) array));
}
}
/**
* Creates a {@link List} containing the elements of this stream, then
* performs finishing transformation and returns its result. There are no
* guarantees on the type, serializability or thread-safety of the
* {@code List} created.
*
* <p>
* This is a terminal operation.
*
* @param <R> the type of the result
* @param finisher a function to be applied to the intermediate list
* @return result of applying the finisher transformation to the list of the
* stream elements.
* @since 0.2.3
* @see #toList()
*/
public <R> R toListAndThen(Function<? super List<T>, R> finisher) {
if (context.fjp != null)
return context.terminate(() -> finisher.apply(toList()));
return finisher.apply(toList());
}
/**
* Returns a {@link Set} containing the elements of this stream. The
* returned {@code Set} is guaranteed to be mutable, but there are no
* guarantees on the type, serializability, or thread-safety; if more
* control over the returned {@code Set} is required, use
* {@link #toCollection(Supplier)}.
*
* <p>
* This is a terminal operation.
*
* @return a {@code Set} containing the elements of this stream
* @see Collectors#toSet()
*/
public Set<T> toSet() {
return rawCollect(Collectors.toSet());
}
/**
* Returns an immutable {@link Set} containing the elements of this stream.
* There's no guarantees on exact type of the returned {@code Set}. In
* particular, no specific element order in the resulting set is guaranteed.
* The returned {@code Set} is guaranteed to be serializable if all its
* elements are serializable.
*
* <p>
* This is a terminal operation.
*
* @return a {@code Set} containing the elements of this stream
* @see #toSet()
* @since 0.6.3
*/
public Set<T> toImmutableSet() {
Set<T> result = toSet();
if (result.size() == 0)
return Collections.emptySet();
return Collections.unmodifiableSet(result);
}
/**
* Creates a {@link Set} containing the elements of this stream, then
* performs finishing transformation and returns its result. There are no
* guarantees on the type, serializability or thread-safety of the
* {@code Set} created.
*
* <p>
* This is a terminal operation.
*
* @param <R> the result type
* @param finisher a function to be applied to the intermediate {@code Set}
* @return result of applying the finisher transformation to the {@code Set}
* of the stream elements.
* @since 0.2.3
* @see #toSet()
*/
public <R> R toSetAndThen(Function<? super Set<T>, R> finisher) {
if (context.fjp != null)
return context.terminate(() -> finisher.apply(toSet()));
return finisher.apply(toSet());
}
/**
* Returns a {@link Collection} containing the elements of this stream. The
* {@code Collection} is created by the provided factory.
*
* <p>
* This is a terminal operation.
*
* @param <C> the type of the resulting {@code Collection}
* @param collectionFactory a {@code Supplier} which returns a new, empty
* {@code Collection} of the appropriate type
* @return a {@code Collection} containing the elements of this stream
* @see Collectors#toCollection(Supplier)
*/
public <C extends Collection<T>> C toCollection(Supplier<C> collectionFactory) {
return rawCollect(Collectors.toCollection(collectionFactory));
}
/**
* Folds the elements of this stream using the provided seed object and
* accumulation function, going left to right. This is equivalent to:
*
* <pre>
* {@code
* U result = seed;
* for (T element : this stream)
* result = accumulator.apply(result, element)
* return result;
* }
* </pre>
*
* <p>
* This is a terminal operation.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly left to right. If your accumulator function is
* associative and you can provide a combiner function, consider using
* {@link #reduce(Object, BiFunction, BinaryOperator)} method.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* @param <U> The type of the result
* @param seed the starting value
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the result of the folding
* @see #foldRight(Object, BiFunction)
* @see #reduce(Object, BinaryOperator)
* @see #reduce(Object, BiFunction, BinaryOperator)
* @since 0.2.0
*/
public <U> U foldLeft(U seed, BiFunction<U, ? super T, U> accumulator) {
Box<U> result = new Box<>(seed);
forEachOrdered(t -> result.a = accumulator.apply(result.a, t));
return result.a;
}
/**
* Folds the elements of this stream using the provided accumulation
* function, going left to right. This is equivalent to:
*
* <pre>
* {@code
* boolean foundAny = false;
* T result = null;
* for (T element : this stream) {
* if (!foundAny) {
* foundAny = true;
* result = element;
* }
* else
* result = accumulator.apply(result, element);
* }
* return foundAny ? Optional.of(result) : Optional.empty();
* }
* </pre>
*
* <p>
* This is a terminal operation.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly left to right. If your accumulator function is
* associative, consider using {@link #reduce(BinaryOperator)} method.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the result of the folding
* @see #foldLeft(Object, BiFunction)
* @see #foldRight(BinaryOperator)
* @see #reduce(BinaryOperator)
* @since 0.4.0
*/
public Optional<T> foldLeft(BinaryOperator<T> accumulator) {
Box<T> result = new Box<>(none());
forEachOrdered(t -> result.a = result.a == NONE ? t : accumulator.apply(result.a, t));
return result.a == NONE ? Optional.empty() : Optional.of(result.a);
}
/**
* Folds the elements of this stream using the provided seed object and
* accumulation function, going right to left.
*
* <p>
* This is a terminal operation.
*
* <p>
* As this method must process elements strictly right to left, it cannot
* start processing till all the previous stream stages complete. Also it
* requires intermediate memory to store the whole content of the stream as
* the stream natural order is left to right. If your accumulator function
* is associative and you can provide a combiner function, consider using
* {@link #reduce(Object, BiFunction, BinaryOperator)} method.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* @param <U> The type of the result
* @param seed the starting value
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the result of the folding
* @see #foldLeft(Object, BiFunction)
* @see #reduce(Object, BinaryOperator)
* @see #reduce(Object, BiFunction, BinaryOperator)
* @since 0.2.2
*/
public <U> U foldRight(U seed, BiFunction<? super T, U, U> accumulator) {
return toListAndThen(list -> {
U result = seed;
for (int i = list.size() - 1; i >= 0; i--)
result = accumulator.apply(list.get(i), result);
return result;
});
}
/**
* Folds the elements of this stream using the provided accumulation
* function, going right to left.
*
* <p>
* This is a terminal operation.
*
* <p>
* As this method must process elements strictly right to left, it cannot
* start processing till all the previous stream stages complete. Also it
* requires intermediate memory to store the whole content of the stream as
* the stream natural order is left to right. If your accumulator function
* is associative, consider using {@link #reduce(BinaryOperator)} method.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the result of the folding
* @see #foldRight(Object, BiFunction)
* @see #foldLeft(BinaryOperator)
* @see #reduce(BinaryOperator)
* @since 0.4.0
*/
public Optional<T> foldRight(BinaryOperator<T> accumulator) {
return this.<Optional<T>> toListAndThen(list -> {
if (list.isEmpty())
return Optional.empty();
int i = list.size() - 1;
T result = list.get(i--);
for (; i >= 0; i--)
result = accumulator.apply(list.get(i), result);
return Optional.of(result);
});
}
/**
* Produces a list containing cumulative results of applying the
* accumulation function going left to right using given seed value.
*
* <p>
* This is a terminal operation.
*
* <p>
* The resulting {@link List} is guaranteed to be mutable.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly left to right.
*
* @param <U> The type of the result
* @param seed the starting value
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the {@code List} where the first element is the seed and every
* successor element is the result of applying accumulator function
* to the previous list element and the corresponding stream
* element. The resulting list is one element longer than this
* stream.
* @see #foldLeft(Object, BiFunction)
* @see #scanRight(Object, BiFunction)
* @since 0.2.1
*/
public <U> List<U> scanLeft(U seed, BiFunction<U, ? super T, U> accumulator) {
List<U> result = new ArrayList<>();
result.add(seed);
forEachOrdered(t -> result.add(accumulator.apply(result.get(result.size() - 1), t)));
return result;
}
/**
* Produces a list containing cumulative results of applying the
* accumulation function going left to right.
*
* <p>
* This is a terminal operation.
*
* <p>
* The resulting {@link List} is guaranteed to be mutable.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly left to right.
*
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the {@code List} where the first element is the first element of
* this stream and every successor element is the result of applying
* accumulator function to the previous list element and the
* corresponding stream element. The resulting list has the same
* size as this stream.
* @see #foldLeft(BinaryOperator)
* @see #scanRight(BinaryOperator)
* @see #prefix(BinaryOperator)
* @since 0.4.0
*/
public List<T> scanLeft(BinaryOperator<T> accumulator) {
List<T> result = new ArrayList<>();
forEachOrdered(t -> {
if (result.isEmpty())
result.add(t);
else
result.add(accumulator.apply(result.get(result.size() - 1), t));
});
return result;
}
/**
* Produces a list containing cumulative results of applying the
* accumulation function going right to left using given seed value.
*
* <p>
* This is a terminal operation.
*
* <p>
* The resulting {@link List} is guaranteed to be mutable.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly right to left.
*
* @param <U> The type of the result
* @param seed the starting value
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the {@code List} where the last element is the seed and every
* predecessor element is the result of applying accumulator
* function to the corresponding stream element and the next list
* element. The resulting list is one element longer than this
* stream.
* @see #scanLeft(Object, BiFunction)
* @see #foldRight(Object, BiFunction)
* @since 0.2.2
*/
@SuppressWarnings("unchecked")
public <U> List<U> scanRight(U seed, BiFunction<? super T, U, U> accumulator) {
return toListAndThen(list -> {
// Reusing the list for different object type as it will save memory
List<U> result = (List<U>) list;
result.add(seed);
for (int i = result.size() - 2; i >= 0; i--) {
result.set(i, accumulator.apply((T) result.get(i), result.get(i + 1)));
}
return result;
});
}
/**
* Produces a collection containing cumulative results of applying the
* accumulation function going right to left.
*
* <p>
* This is a terminal operation.
*
* <p>
* The result {@link List} is guaranteed to be mutable.
*
* <p>
* For parallel stream it's not guaranteed that accumulator will always be
* executed in the same thread.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly right to left.
*
* @param accumulator a <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for incorporating an additional element into a result
* @return the {@code List} where the last element is the last element of
* this stream and every predecessor element is the result of
* applying accumulator function to the corresponding stream element
* and the next list element. The resulting list is one element
* longer than this stream.
* @see #scanLeft(BinaryOperator)
* @see #foldRight(BinaryOperator)
* @since 0.4.0
*/
public List<T> scanRight(BinaryOperator<T> accumulator) {
return toListAndThen(list -> {
for (int i = list.size() - 2; i >= 0; i--) {
list.set(i, accumulator.apply(list.get(i), list.get(i + 1)));
}
return list;
});
}
/**
* Returns a stream consisting of the remaining elements of this stream
* after discarding the first {@code n} elements of the stream even if the
* stream is unordered. If this stream contains fewer than {@code n}
* elements then an empty stream will be returned.
*
* <p>
* This is a stateful <a
* href="package-summary.html#StreamOps">quasi-intermediate</a> operation.
* Unlike {@link #skip(long)} it skips the first elements even if the stream
* is unordered. The main purpose of this method is to workaround the
* problem of skipping the first elements from non-sized source with further
* parallel processing and unordered terminal operation (such as
* {@link #forEach(Consumer)}). For example,
* {@code StreamEx.ofLines(br).skip(1).parallel().toSet()} will skip
* arbitrary line, but
* {@code StreamEx.ofLines(br).skipOrdered(1).parallel().toSet()} will skip
* the first one. This problem was fixed in OracleJDK 8u60.
*
* <p>
* Also it behaves much better with infinite streams processed in parallel.
*
* <p>
* For sequential streams this method behaves exactly like
* {@link #skip(long)}.
*
* @param n the number of leading elements to skip
* @return the new stream
* @throws IllegalArgumentException if {@code n} is negative
* @see #skip(long)
* @since 0.3.2
*/
public S skipOrdered(long n) {
return supply((isParallel() ? StreamSupport.stream(spliterator(), false) : stream()).skip(n).spliterator());
}
/**
* Returns a stream consisting of all elements from this stream until the
* first element which does not match the given predicate is found.
*
* <p>
* This is a short-circuiting stateful operation. It can be either <a
* href="package-summary.html#StreamOps">intermediate or
* quasi-intermediate</a>. When using with JDK 1.9 or higher it calls the
* corresponding JDK 1.9 implementation. When using with JDK 1.8 it uses own
* implementation.
*
* <p>
* While this operation is quite cheap for sequential stream, it can be
* quite expensive on parallel pipelines. Using unordered source or making it
* explicitly unordered with {@link #unordered()} call may improve the parallel
* processing performance if semantics permit.
*
* @param predicate a non-interfering, stateless predicate to apply to
* elements.
* @return the new stream.
* @since 0.3.6
* @see #takeWhileInclusive(Predicate)
* @see #dropWhile(Predicate)
*/
public S takeWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
return VER_SPEC.callWhile(this, predicate, false);
}
/**
* Returns a stream consisting of all elements from this stream until the
* first element which does not match the given predicate is found
* (including the first mismatching element).
*
* <p>
* This is a <a href="package-summary.html#StreamOps">quasi-intermediate
* operation</a>.
*
* <p>
* While this operation is quite cheap for sequential stream, it can be
* quite expensive on parallel pipelines. Using unordered source or making it
* explicitly unordered with {@link #unordered()} call may improve the parallel
* processing performance if semantics permit.
*
* @param predicate a non-interfering, stateless predicate to apply to
* elements.
* @return the new stream.
* @since 0.5.5
* @see #takeWhile(Predicate)
*/
public S takeWhileInclusive(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
Spliterator<T> spltr = spliterator();
return supply(
spltr.hasCharacteristics(Spliterator.ORDERED) ? new TakeDrop.TDOfRef<>(spltr, false, true, predicate)
: new TakeDrop.UnorderedTDOfRef<T>(spltr, false, true, predicate));
}
/**
* Returns a stream consisting of all elements from this stream starting
* from the first element which does not match the given predicate. If the
* predicate is true for all stream elements, an empty stream is returned.
*
* <p>
* This is a stateful operation. It can be either <a
* href="package-summary.html#StreamOps">intermediate or
* quasi-intermediate</a>. When using with JDK 1.9 or higher it calls the
* corresponding JDK 1.9 implementation. When using with JDK 1.8 it uses own
* implementation.
*
* <p>
* While this operation is quite cheap for sequential stream, it can be
* quite expensive on parallel pipelines. Using unordered source or making it
* explicitly unordered with {@link #unordered()} call may improve the parallel
* processing performance if semantics permit.
*
* @param predicate a non-interfering, stateless predicate to apply to
* elements.
* @return the new stream.
* @since 0.3.6
*/
public S dropWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
return VER_SPEC.callWhile(this, predicate, true);
}
/**
* Returns a stream containing cumulative results of applying the
* accumulation function going left to right.
*
* <p>
* This is a stateful <a
* href="package-summary.html#StreamOps">quasi-intermediate</a> operation.
*
* <p>
* This operation resembles {@link #scanLeft(BinaryOperator)}, but unlike
* {@code scanLeft} this operation is intermediate and accumulation function
* must be associative.
*
* <p>
* This method cannot take all the advantages of parallel streams as it must
* process elements strictly left to right. Using an unordered source or
* removing the ordering constraint with {@link #unordered()} may improve
* the parallel processing speed.
*
* @param op an <a
* href="package-summary.html#Associativity">associative</a>, <a
* href="package-summary.html#NonInterference">non-interfering </a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* function for computing the next element based on the previous one
* @return the new stream.
* @see #scanLeft(BinaryOperator)
* @since 0.6.1
*/
public S prefix(BinaryOperator<T> op) {
Spliterator<T> spltr = spliterator();
return supply(spltr.hasCharacteristics(Spliterator.ORDERED) ? new PrefixOps.OfRef<>(spltr, op)
: new PrefixOps.OfUnordRef<T>(spltr, op));
}
// Necessary to generate proper JavaDoc
@SuppressWarnings("unchecked")
@Override
public <U> U chain(Function<? super S, U> mapper) {
return mapper.apply((S)this);
}
}