com.landawn.abacus.util.stream.IntStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-common Show documentation
Show all versions of abacus-common Show documentation
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
/*
* Copyright (C) 2016, 2017, 2018, 2019 HaiYang Li
*
* 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.landawn.abacus.util.stream;
import java.nio.IntBuffer;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator;
import java.util.Queue;
import java.util.Random;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntSupplier;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.Collector;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.IntermediateOp;
import com.landawn.abacus.annotation.LazyEvaluation;
import com.landawn.abacus.annotation.ParallelSupported;
import com.landawn.abacus.annotation.SequentialOnly;
import com.landawn.abacus.annotation.TerminalOp;
import com.landawn.abacus.util.Array;
import com.landawn.abacus.util.AsyncExecutor;
import com.landawn.abacus.util.ClassUtil;
import com.landawn.abacus.util.ContinuableFuture;
import com.landawn.abacus.util.Duration;
import com.landawn.abacus.util.Fn.FI;
import com.landawn.abacus.util.Holder;
import com.landawn.abacus.util.IndexedInt;
import com.landawn.abacus.util.IntIterator;
import com.landawn.abacus.util.IntList;
import com.landawn.abacus.util.IntSummaryStatistics;
import com.landawn.abacus.util.MergeResult;
import com.landawn.abacus.util.MutableInt;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.Pair;
import com.landawn.abacus.util.Percentage;
import com.landawn.abacus.util.RateLimiter;
import com.landawn.abacus.util.Strings;
import com.landawn.abacus.util.Throwables;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalInt;
import com.landawn.abacus.util.function.IntBiFunction;
import com.landawn.abacus.util.function.IntBiPredicate;
import com.landawn.abacus.util.function.IntMapMultiConsumer;
import com.landawn.abacus.util.function.IntNFunction;
import com.landawn.abacus.util.function.IntTernaryOperator;
import com.landawn.abacus.util.function.IntToByteFunction;
import com.landawn.abacus.util.function.IntToCharFunction;
import com.landawn.abacus.util.function.IntToFloatFunction;
import com.landawn.abacus.util.function.IntToShortFunction;
import com.landawn.abacus.util.function.IntTriPredicate;
/**
* The Stream will be automatically closed after execution(A terminal method is executed/triggered).
*
* @see BaseStream
* @see Stream
*/
@com.landawn.abacus.annotation.Immutable
@LazyEvaluation
public abstract class IntStream extends StreamBase {
static final Random RAND = new SecureRandom();
IntStream(final boolean sorted, final Collection closeHandlers) {
super(sorted, null, closeHandlers);
}
/**
*
*
* @param rateLimiter
* @return
*/
@Override
public IntStream rateLimited(final RateLimiter rateLimiter) {
checkArgNotNull(rateLimiter, "rateLimiter");
final IntConsumer action = it -> rateLimiter.acquire();
if (isParallel()) {
return sequential().onEach(action).parallel(maxThreadNum(), executorNumForVirtualThread(), splitor(), asyncExecutor(), cancelUncompletedThreads());
} else {
return onEach(action);
}
}
/**
*
*
* @param delay
* @return
*/
@Override
public IntStream delay(final Duration delay) {
checkArgNotNull(delay, "delay");
final long millis = delay.toMillis();
final IntConsumer action = it -> N.sleepUninterruptibly(millis);
if (isParallel()) {
return sequential().onEach(action).parallel(maxThreadNum(), executorNumForVirtualThread(), splitor(), asyncExecutor(), cancelUncompletedThreads());
} else {
return onEach(action);
}
}
/**
*
*
* @param predicate
* @return
*/
@Override
public IntStream skipUntil(final IntPredicate predicate) {
assertNotClosed();
return dropWhile(t -> !predicate.test(t));
}
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream map(IntUnaryOperator mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract CharStream mapToChar(IntToCharFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract ByteStream mapToByte(IntToByteFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract ShortStream mapToShort(IntToShortFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract LongStream mapToLong(IntToLongFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract FloatStream mapToFloat(IntToFloatFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract DoubleStream mapToDouble(IntToDoubleFunction mapper);
/**
*
*
* @param
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract Stream mapToObj(IntFunction extends T> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream flatMap(IntFunction extends IntStream> mapper);
// public abstract IntStream flatmap(IntFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream flatmap(IntFunction mapper); //NOSONAR
/**
*
*
* @param mapper
* @return
*/
@Beta
@ParallelSupported
@IntermediateOp
public abstract IntStream flattmap(IntFunction extends java.util.stream.IntStream> mapper); //NOSONAR
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract CharStream flatMapToChar(IntFunction extends CharStream> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract ByteStream flatMapToByte(IntFunction extends ByteStream> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract ShortStream flatMapToShort(IntFunction extends ShortStream> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract LongStream flatMapToLong(IntFunction extends LongStream> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract FloatStream flatMapToFloat(IntFunction extends FloatStream> mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract DoubleStream flatMapToDouble(IntFunction extends DoubleStream> mapper);
/**
*
*
* @param
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract Stream flatMapToObj(IntFunction extends Stream extends T>> mapper);
/**
*
*
* @param
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract Stream flatmapToObj(IntFunction extends Collection extends T>> mapper); //NOSONAR
/**
*
*
* @param
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract Stream flattMapToObj(IntFunction mapper);
/**
*
*
* @param mapper
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream mapMulti(IntMapMultiConsumer mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
* @param mapper
* @return
*/
@Beta
@ParallelSupported
@IntermediateOp
public abstract IntStream mapPartial(IntFunction mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
* @param mapper
* @return
*/
@Beta
@ParallelSupported
@IntermediateOp
public abstract IntStream mapPartialJdk(IntFunction mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
*
*
* Returns a stream consisting of results of applying the given function to
* the ranges created from the source elements.
* This is a quasi-intermediate
* partial reduction operation.
*
* @param sameRange a non-interfering, stateless predicate to apply to
* the leftmost and next elements which returns true for elements
* which belong to the same range.
* @param mapper a non-interfering, stateless function to apply to the
* range borders and produce the resulting element. If value was
* not merged to the interval, then mapper will receive the same
* value twice, otherwise it will receive the leftmost and the
* rightmost values which were merged to the range.
* @return
* @see #collapse(IntBiPredicate, IntBinaryOperator)
* @see Stream#rangeMap(BiPredicate, BiFunction)
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream rangeMap(final IntBiPredicate sameRange, final IntBinaryOperator mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
*
*
* Returns a stream consisting of results of applying the given function to
* the ranges created from the source elements.
* This is a quasi-intermediate
* partial reduction operation.
*
* @param
* @param sameRange a non-interfering, stateless predicate to apply to
* the leftmost and next elements which returns true for elements
* which belong to the same range.
* @param mapper a non-interfering, stateless function to apply to the
* range borders and produce the resulting element. If value was
* not merged to the interval, then mapper will receive the same
* value twice, otherwise it will receive the leftmost and the
* rightmost values which were merged to the range.
* @return
* @see Stream#rangeMap(BiPredicate, BiFunction)
*/
@SequentialOnly
@IntermediateOp
public abstract Stream rangeMapToObj(final IntBiPredicate sameRange, final IntBiFunction extends T> mapper);
/**
* Merge series of adjacent elements which satisfy the given predicate using
* the merger function and return a new stream.
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param collapsible
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract Stream collapse(final IntBiPredicate collapsible);
/**
* Merge series of adjacent elements which satisfy the given predicate using
* the merger function and return a new stream.
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param collapsible
* @param mergeFunction
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream collapse(final IntBiPredicate collapsible, final IntBinaryOperator mergeFunction);
/**
*
* @param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element.
* @param mergeFunction
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream collapse(final IntTriPredicate collapsible, final IntBinaryOperator mergeFunction);
/**
* Returns a {@code Stream} produced by iterative application of a accumulation function
* to an initial element {@code init} and next element of the current stream.
* Produces a {@code Stream} consisting of {@code init}, {@code acc(init, value1)},
* {@code acc(acc(init, value1), value2)}, etc.
*
* This is an intermediate operation.
*
*
Example:
*
* accumulator: (a, b) -> a + b
* stream: [1, 2, 3, 4, 5]
* result: [1, 3, 6, 10, 15]
*
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param accumulator the accumulation function
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream scan(final IntBinaryOperator accumulator);
/**
* Returns a {@code Stream} produced by iterative application of a accumulation function
* to an initial element {@code init} and next element of the current stream.
* Produces a {@code Stream} consisting of {@code init}, {@code acc(init, value1)},
* {@code acc(acc(init, value1), value2)}, etc.
*
* This is an intermediate operation.
*
*
Example:
*
* init:10
* accumulator: (a, b) -> a + b
* stream: [1, 2, 3, 4, 5]
* result: [11, 13, 16, 20, 25]
*
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param init the initial value. it's only used once by accumulator
to calculate the fist element in the returned stream.
* It will be ignored if this stream is empty and won't be the first element of the returned stream.
*
* @param accumulator the accumulation function
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream scan(final int init, final IntBinaryOperator accumulator);
/**
*
* @param init
* @param accumulator
* @param initIncluded
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream scan(final int init, final IntBinaryOperator accumulator, final boolean initIncluded);
/**
*
*
* @param a
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream prepend(final int... a);
/**
*
*
* @param a
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream append(final int... a);
/**
*
*
* @param a
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream appendIfEmpty(final int... a);
/**
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param n
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream top(int n);
/**
*
*
* This method only runs sequentially, even in parallel stream.
*
* @param n
* @param comparator
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream top(final int n, Comparator super Integer> comparator);
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract IntList toIntList();
/**
*
*
* @param
* @param
* @param
* @param
* @param keyMapper
* @param valueMapper
* @return
* @throws E
* @throws E2
* @see Collectors#toMap(Function, Function)
*/
@ParallelSupported
@TerminalOp
public abstract Map toMap(Throwables.IntFunction extends K, E> keyMapper,
Throwables.IntFunction extends V, E2> valueMapper) throws E, E2;
/**
*
*
* @param
* @param
* @param
* @param
* @param
* @param keyMapper
* @param valueMapper
* @param mapFactory
* @return
* @throws E
* @throws E2
* @see Collectors#toMap(Function, Function, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception, E2 extends Exception> M toMap(Throwables.IntFunction extends K, E> keyMapper,
Throwables.IntFunction extends V, E2> valueMapper, Supplier extends M> mapFactory) throws E, E2;
/**
*
*
* @param
* @param
* @param
* @param
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @return
* @throws E
* @throws E2
* @see Collectors#toMap(Function, Function, BinaryOperator)
*/
@ParallelSupported
@TerminalOp
public abstract Map toMap(Throwables.IntFunction extends K, E> keyMapper,
Throwables.IntFunction extends V, E2> valueMapper, BinaryOperator mergeFunction) throws E, E2;
/**
*
*
* @param
* @param
* @param
* @param
* @param
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @param mapFactory
* @return
* @throws E
* @throws E2
* @see Collectors#toMap(Function, Function, BinaryOperator, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception, E2 extends Exception> M toMap(Throwables.IntFunction extends K, E> keyMapper,
Throwables.IntFunction extends V, E2> valueMapper, BinaryOperator mergeFunction, Supplier extends M> mapFactory) throws E, E2;
/**
*
*
* @param
* @param
* @param
* @param keyMapper
* @param downstream
* @return
* @throws E
* @see Collectors#groupingBy(Function, Collector)
*/
@ParallelSupported
@TerminalOp
public abstract Map groupTo(Throwables.IntFunction extends K, E> keyMapper,
final Collector super Integer, ?, D> downstream) throws E;
/**
*
*
* @param
* @param
* @param
* @param
* @param keyMapper
* @param downstream
* @param mapFactory
* @return
* @throws E
* @see Collectors#groupingBy(Function, Collector, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception> M groupTo(Throwables.IntFunction extends K, E> keyMapper,
final Collector super Integer, ?, D> downstream, final Supplier extends M> mapFactory) throws E;
/**
*
*
* @param identity
* @param op
* @return
*/
@ParallelSupported
@TerminalOp
public abstract int reduce(int identity, IntBinaryOperator op);
/**
*
*
* @param op
* @return
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt reduce(IntBinaryOperator op);
/**
*
* @param
* @param supplier
* @param accumulator
* @param combiner
* @return
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@ParallelSupported
@TerminalOp
public abstract R collect(Supplier supplier, ObjIntConsumer super R> accumulator, BiConsumer combiner);
/**
* Only call this method when the returned type {@code R} is one types: {@code Collection/Map/StringBuilder/Multiset/LongMultiset/Multimap/BooleanList/IntList/.../DoubleList}.
* Otherwise, please call {@link #collect(Supplier, ObjIntConsumer, BiConsumer)}.
*
* @param
* @param supplier
* @param accumulator
* @return
* @see #collect(Supplier, ObjIntConsumer, BiConsumer)
* @see Stream#collect(Supplier, BiConsumer)
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@ParallelSupported
@TerminalOp
public abstract R collect(Supplier supplier, ObjIntConsumer super R> accumulator);
/**
*
*
* @param
* @param action
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract void forEach(final Throwables.IntConsumer action) throws E;
/**
*
*
* @param
* @param action
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract void forEachIndexed(Throwables.IndexedIntConsumer action) throws E;
/**
*
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract boolean anyMatch(final Throwables.IntPredicate predicate) throws E;
/**
*
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract boolean allMatch(final Throwables.IntPredicate predicate) throws E;
/**
*
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract boolean noneMatch(final Throwables.IntPredicate predicate) throws E;
/**
*
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt findFirst(final Throwables.IntPredicate predicate) throws E;
/**
* Returns the first element matched by {@code predicateForFirst} if found or the first element if this stream is not empty
* Otherwise an empty {@code OptionalInt} will be returned.
*
* @param
* @param predicateForFirst
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt findFirstOrAny(Throwables.IntPredicate predicateForFirst) throws E;
/**
* Returns the first element matched by {@code predicateForFirst} if found or the last element if this stream is not empty
* Otherwise an empty {@code OptionalInt} will be returned.
*
* @param
* @param predicateForFirst
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt findFirstOrLast(Throwables.IntPredicate predicateForFirst) throws E;
/**
* Consider using: {@code stream.reversed().findFirst(predicate)} for better performance if possible.
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt findLast(final Throwables.IntPredicate predicate) throws E;
/**
*
*
* @param
* @param predicate
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalInt findAny(final Throwables.IntPredicate predicate) throws E;
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract OptionalInt min();
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract OptionalInt max();
/**
*
* @param k
* @return OptionalByte.empty() if there is no element or count less than k, otherwise the kth largest element.
*/
@SequentialOnly
@TerminalOp
public abstract OptionalInt kthLargest(int k);
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract int sum();
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract OptionalDouble average();
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract IntSummaryStatistics summarize();
/**
*
*
* @return
*/
@SequentialOnly
@TerminalOp
public abstract Pair>> summarizeAndPercentiles();
// /**
// *
// * @param b
// * @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
// * @return
// * @deprecated replaced by {@code mergeWith(IntStream, IntBiFunction)}
// * @see #mergeWith(IntStream, IntBiFunction)
// */
// @SequentialOnly
// @IntermediateOp
// @Deprecated
// public IntStream merge(final IntStream b, final IntBiFunction nextSelector) {
// return mergeWith(b, nextSelector);
// }
/**
*
* @param b
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract IntStream mergeWith(final IntStream b, final IntBiFunction nextSelector);
/**
*
*
* @param b
* @param zipFunction
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream zipWith(IntStream b, IntBinaryOperator zipFunction);
/**
*
*
* @param b
* @param c
* @param zipFunction
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream zipWith(IntStream b, IntStream c, IntTernaryOperator zipFunction);
/**
*
*
* @param b
* @param valueForNoneA
* @param valueForNoneB
* @param zipFunction
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream zipWith(IntStream b, int valueForNoneA, int valueForNoneB, IntBinaryOperator zipFunction);
/**
*
*
* @param b
* @param c
* @param valueForNoneA
* @param valueForNoneB
* @param valueForNoneC
* @param zipFunction
* @return
*/
@ParallelSupported
@IntermediateOp
public abstract IntStream zipWith(IntStream b, IntStream c, int valueForNoneA, int valueForNoneB, int valueForNoneC, IntTernaryOperator zipFunction);
/**
*
*
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract LongStream asLongStream();
/**
*
*
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract FloatStream asFloatStream();
/**
*
*
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract DoubleStream asDoubleStream();
/**
*
*
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract java.util.stream.IntStream toJdkStream();
// No performance improvement.
// /**
// * Temporarily switch the stream to Jdk parallel stream for operation {@code ops} and then switch back to sequence stream.
// *
// * {@code stream.(switchToJdkStream).parallel().ops(map/filter/...).(switchBack).sequence()}
// *
// * @param
// * @param op
// * @return
// */
// @Beta
// @IntermediateOp
// public IntStream sjps(Function super java.util.stream.IntStream, ? extends java.util.stream.IntStream> op) {
// if (this.isParallel()) {
// return of(op.apply(this.toJdkStream())).sequential();
// } else {
// return of(op.apply(this.toJdkStream().parallel()));
// }
// }
/**
*
*
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract Stream boxed();
/**
* Remember to close this Stream after the iteration is done, if needed.
*
* @return
*/
@SequentialOnly
@Override
public IntIterator iterator() {
assertNotClosed();
if (!isEmptyCloseHandlers(closeHandlers) && logger.isWarnEnabled()) {
logger.warn("### Remember to close " + ClassUtil.getSimpleClassName(getClass()));
}
return iteratorEx();
}
abstract IntIteratorEx iteratorEx();
/**
*
*
* @return
*/
public static IntStream empty() {
return new ArrayIntStream(N.EMPTY_INT_ARRAY, true, null);
}
/**
*
*
* @param e
* @return
*/
public static IntStream ofNullable(final Integer e) {
return e == null ? empty() : of(e);
}
/**
*
*
* @param a
* @return
*/
@SafeVarargs
public static IntStream of(final int... a) {
return N.isEmpty(a) ? empty() : new ArrayIntStream(a);
}
/**
*
*
* @param a
* @param startIndex
* @param endIndex
* @return
*/
public static IntStream of(final int[] a, final int startIndex, final int endIndex) {
return N.isEmpty(a) && (startIndex == 0 && endIndex == 0) ? empty() : new ArrayIntStream(a, startIndex, endIndex);
}
/**
*
*
* @param a
* @return
*/
public static IntStream of(final Integer[] a) {
return Stream.of(a).mapToInt(FI.unbox());
}
/**
*
*
* @param a
* @param startIndex
* @param endIndex
* @return
*/
public static IntStream of(final Integer[] a, final int startIndex, final int endIndex) {
return Stream.of(a, startIndex, endIndex).mapToInt(FI.unbox());
}
/**
*
*
* @param c
* @return
*/
public static IntStream of(final Collection c) {
return Stream.of(c).mapToInt(FI.unbox());
}
/**
*
*
* @param iterator
* @return
*/
public static IntStream of(final IntIterator iterator) {
return iterator == null ? empty() : new IteratorIntStream(iterator);
}
/**
*
*
* @param stream
* @return
*/
public static IntStream of(final java.util.stream.IntStream stream) {
if (stream == null) {
return empty();
}
return of(new IntIteratorEx() {
private PrimitiveIterator.OfInt iter = null;
@Override
public boolean hasNext() {
if (iter == null) {
iter = stream.iterator();
}
return iter.hasNext();
}
@Override
public int nextInt() {
if (iter == null) {
iter = stream.iterator();
}
return iter.nextInt();
}
@Override
public long count() {
return iter == null ? stream.count() : super.count();
}
@Override
public void advance(long n) {
if (iter == null) {
iter = stream.skip(n).iterator();
} else {
super.advance(n);
}
}
@Override
public int[] toArray() {
return iter == null ? stream.toArray() : super.toArray();
}
}).transform(s -> stream.isParallel() ? s.parallel() : s.sequential()).onClose(stream::close);
}
/**
*
*
* @param op
* @return
*/
public static IntStream of(final OptionalInt op) {
return op == null || !op.isPresent() ? IntStream.empty() : IntStream.of(op.get());
}
/**
*
*
* @param op
* @return
*/
public static IntStream of(final java.util.OptionalInt op) {
return op == null || !op.isPresent() ? IntStream.empty() : IntStream.of(op.getAsInt());
}
/**
*
*
* @param buf
* @return
*/
public static IntStream of(final IntBuffer buf) {
if (buf == null) {
return empty();
}
return range(buf.position(), buf.limit()).map(buf::get);
}
/**
*
*
* @param str
* @return
*/
public static IntStream ofCodePoints(final CharSequence str) {
if (Strings.isEmpty(str)) {
return empty();
}
final IntIterator iter = new IntIterator() {
private final int len = str.length();
private int cursor = 0;
private char c1 = 0;
private char c2 = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public int nextInt() {
if (cursor >= len) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
c1 = str.charAt(cursor++);
if (Character.isHighSurrogate(c1) && cursor < len) {
c2 = str.charAt(cursor);
if (Character.isLowSurrogate(c2)) {
cursor++;
return Character.toCodePoint(c1, c2);
}
}
return c1;
}
};
return of(iter);
}
/**
* Lazy evaluation.
*
*
* This is equal to: {@code Stream.just(supplier).flatMapToInt(it -> it.get())}.
*
* @param supplier
* @return
*/
public static IntStream defer(final Supplier supplier) {
N.checkArgNotNull(supplier, "supplier");
return Stream.just(supplier).flatMapToInt(Supplier::get);
}
// /**
// * Lazy evaluation.
// *
// *
// * This is equal to: {@code Stream.just(supplier).flatMapToInt(it -> it.get().stream())}.
// *
// * @param supplier
// * @return
// */
// @Beta
// public static IntStream from(final Supplier supplier) {
// N.checkArgNotNull(supplier, "supplier");
//
// return Stream.just(supplier).flatMapToInt(it -> it.get().stream());
// }
private static final Function flatMapper = IntStream::of;
private static final Function flattMapper = IntStream::flatten;
/**
*
*
* @param a
* @return
*/
public static IntStream flatten(final int[][] a) {
return N.isEmpty(a) ? empty() : Stream.of(a).flatMapToInt(flatMapper);
}
/**
*
*
* @param a
* @param vertically
* @return
*/
public static IntStream flatten(final int[][] a, final boolean vertically) {
if (N.isEmpty(a)) {
return empty();
} else if (a.length == 1) {
return of(a[0]);
} else if (!vertically) {
return Stream.of(a).flatMapToInt(flatMapper);
}
long n = 0;
for (int[] e : a) {
n += N.len(e);
}
if (n == 0) {
return empty();
}
final int rows = N.len(a);
final long count = n;
final IntIterator iter = new IntIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public int nextInt() {
if (cnt++ >= count) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
if (rowNum == rows) {
rowNum = 0;
colNum++;
}
while (a[rowNum] == null || colNum >= a[rowNum].length) {
if (rowNum < rows - 1) {
rowNum++;
} else {
rowNum = 0;
colNum++;
}
}
return a[rowNum++][colNum];
}
};
return of(iter);
}
/**
*
*
* @param a
* @param valueForNone
* @param vertically
* @return
*/
public static IntStream flatten(final int[][] a, final int valueForNone, final boolean vertically) {
if (N.isEmpty(a)) {
return empty();
} else if (a.length == 1) {
return of(a[0]);
}
long n = 0;
int maxLen = 0;
for (int[] e : a) {
n += N.len(e);
maxLen = N.max(maxLen, N.len(e));
}
if (n == 0) {
return empty();
}
final int rows = N.len(a);
final int cols = maxLen;
final long count = (long) rows * cols;
IntIterator iter = null;
if (vertically) {
iter = new IntIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public int nextInt() {
if (cnt++ >= count) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
if (rowNum == rows) {
rowNum = 0;
colNum++;
}
if (a[rowNum] == null || colNum >= a[rowNum].length) {
rowNum++;
return valueForNone;
} else {
return a[rowNum++][colNum];
}
}
};
} else {
iter = new IntIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public int nextInt() {
if (cnt++ >= count) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
if (colNum >= cols) {
colNum = 0;
rowNum++;
}
if (a[rowNum] == null || colNum >= a[rowNum].length) {
colNum++;
return valueForNone;
} else {
return a[rowNum][colNum++];
}
}
};
}
return of(iter);
}
/**
*
*
* @param a
* @return
*/
public static IntStream flatten(final int[][][] a) {
return N.isEmpty(a) ? empty() : Stream.of(a).flatMapToInt(flattMapper);
}
//
// /**
// *
// * @param a
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// @SafeVarargs
// public static IntStream from(final char... a) {
// return N.isEmpty(a) ? empty() : from(a, 0, a.length);
// }
//
// /**
// *
// * @param a
// * @param fromIndex
// * @param toIndex
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// public static IntStream from(final char[] a, final int fromIndex, final int toIndex) {
// N.checkFromToIndex(fromIndex, toIndex, N.len(a));
//
// if (fromIndex == toIndex) {
// return empty();
// }
//
// return new IteratorIntStream(new IntIteratorEx() {
// private int cursor = fromIndex;
//
// @Override
// public boolean hasNext() {
// return cursor < toIndex;
// }
//
// @Override
// public int nextInt() {
// if (cursor >= toIndex) {
// throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
// }
//
// return a[cursor++];
// }
//
// @Override
// public long count() {
// return toIndex - cursor; //NOSONAR
// }
//
// @Override
// public void advance(long n) {
// cursor = n < toIndex - cursor ? cursor + (int) n : toIndex;
// }
//
// @Override
// public int[] toArray() {
// final int[] result = new int[toIndex - cursor];
//
// for (int i = cursor; i < toIndex; i++) {
// result[i - cursor] = a[i];
// }
//
// return result;
// }
// });
// }
//
// /**
// *
// * @param a
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// @SafeVarargs
// public static IntStream from(final byte... a) {
// return N.isEmpty(a) ? empty() : from(a, 0, a.length);
// }
//
// /**
// *
// * @param a
// * @param fromIndex
// * @param toIndex
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// public static IntStream from(final byte[] a, final int fromIndex, final int toIndex) {
// N.checkFromToIndex(fromIndex, toIndex, N.len(a));
//
// if (fromIndex == toIndex) {
// return empty();
// }
//
// return new IteratorIntStream(new IntIteratorEx() {
// private int cursor = fromIndex;
//
// @Override
// public boolean hasNext() {
// return cursor < toIndex;
// }
//
// @Override
// public int nextInt() {
// if (cursor >= toIndex) {
// throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
// }
//
// return a[cursor++];
// }
//
// @Override
// public long count() {
// return toIndex - cursor; //NOSONAR
// }
//
// @Override
// public void advance(long n) {
// cursor = n < toIndex - cursor ? cursor + (int) n : toIndex;
// }
//
// @Override
// public int[] toArray() {
// final int[] result = new int[toIndex - cursor];
//
// for (int i = cursor; i < toIndex; i++) {
// result[i - cursor] = a[i];
// }
//
// return result;
// }
// });
// }
//
// /**
// *
// * @param a
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// @SafeVarargs
// public static IntStream from(final short... a) {
// return N.isEmpty(a) ? empty() : from(a, 0, a.length);
// }
//
// /**
// *
// * @param a
// * @param fromIndex
// * @param toIndex
// * @return
// * @deprecated
// */
// @Deprecated
// @Beta
// public static IntStream from(final short[] a, final int fromIndex, final int toIndex) {
// N.checkFromToIndex(fromIndex, toIndex, N.len(a));
//
// if (fromIndex == toIndex) {
// return empty();
// }
//
// return new IteratorIntStream(new IntIteratorEx() {
// private int cursor = fromIndex;
//
// @Override
// public boolean hasNext() {
// return cursor < toIndex;
// }
//
// @Override
// public int nextInt() {
// if (cursor >= toIndex) {
// throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
// }
//
// return a[cursor++];
// }
//
// @Override
// public long count() {
// return toIndex - cursor; //NOSONAR
// }
//
// @Override
// public void advance(long n) {
// cursor = n < toIndex - cursor ? cursor + (int) n : toIndex;
// }
//
// @Override
// public int[] toArray() {
// final int[] result = new int[toIndex - cursor];
//
// for (int i = cursor; i < toIndex; i++) {
// result[i - cursor] = a[i];
// }
//
// return result;
// }
// });
// }
/**
*
*
* @param startInclusive
* @param endExclusive
* @return
*/
public static IntStream range(final int startInclusive, final int endExclusive) {
if (startInclusive >= endExclusive) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private int next = startInclusive;
private long cnt = endExclusive * 1L - startInclusive;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public int nextInt() {
if (cnt-- <= 0) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return next++;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
next += n;
}
@Override
public long count() {
return cnt;
}
@Override
public int[] toArray() {
final int[] result = new int[(int) cnt];
for (int i = 0; i < cnt; i++) {
result[i] = next++;
}
cnt = 0;
return result;
}
});
}
/**
*
*
* @param startInclusive
* @param endExclusive
* @param by
* @return
*/
public static IntStream range(final int startInclusive, final int endExclusive, final int by) {
if (by == 0) {
throw new IllegalArgumentException("'by' can't be zero");
}
if (endExclusive == startInclusive || endExclusive > startInclusive != by > 0) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private int next = startInclusive;
private long cnt = (endExclusive * 1L - startInclusive) / by + ((endExclusive * 1L - startInclusive) % by == 0 ? 0 : 1);
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public int nextInt() {
if (cnt-- <= 0) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
int result = next;
next += by;
return result;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
next += n * by;
}
@Override
public long count() {
return cnt;
}
@Override
public int[] toArray() {
final int[] result = new int[(int) cnt];
for (int i = 0; i < cnt; i++, next += by) {
result[i] = next;
}
cnt = 0;
return result;
}
});
}
/**
*
*
* @param startInclusive
* @param endInclusive
* @return
*/
public static IntStream rangeClosed(final int startInclusive, final int endInclusive) {
if (startInclusive > endInclusive) {
return empty();
} else if (startInclusive == endInclusive) {
return of(startInclusive);
}
return new IteratorIntStream(new IntIteratorEx() {
private int next = startInclusive;
private long cnt = endInclusive * 1L - startInclusive + 1;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public int nextInt() {
if (cnt-- <= 0) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return next++;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
next += n;
}
@Override
public long count() {
return cnt;
}
@Override
public int[] toArray() {
final int[] result = new int[(int) cnt];
for (int i = 0; i < cnt; i++) {
result[i] = next++;
}
cnt = 0;
return result;
}
});
}
/**
*
*
* @param startInclusive
* @param endInclusive
* @param by
* @return
*/
public static IntStream rangeClosed(final int startInclusive, final int endInclusive, final int by) {
if (by == 0) {
throw new IllegalArgumentException("'by' can't be zero");
}
if (endInclusive == startInclusive) {
return of(startInclusive);
} else if (endInclusive > startInclusive != by > 0) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private int next = startInclusive;
private long cnt = (endInclusive * 1L - startInclusive) / by + 1;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public int nextInt() {
if (cnt-- <= 0) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
int result = next;
next += by;
return result;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
next += n * by;
}
@Override
public long count() {
return cnt;
}
@Override
public int[] toArray() {
final int[] result = new int[(int) cnt];
for (int i = 0; i < cnt; i++, next += by) {
result[i] = next;
}
cnt = 0;
return result;
}
});
}
/**
*
*
* @param element
* @param n
* @return
*/
public static IntStream repeat(final int element, final long n) {
N.checkArgNotNegative(n, "n");
if (n == 0) {
return empty();
} else if (n < 10) {
return of(Array.repeat(element, (int) n));
}
return new IteratorIntStream(new IntIteratorEx() {
private long cnt = n;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public int nextInt() {
if (cnt-- <= 0) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return element;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
}
@Override
public long count() {
return cnt;
}
@Override
public int[] toArray() {
final int[] result = new int[(int) cnt];
for (int i = 0; i < cnt; i++) {
result[i] = element;
}
cnt = 0;
return result;
}
});
}
/**
*
*
* @return
*/
public static IntStream random() {
return generate(RAND::nextInt);
}
/**
*
*
* @param startInclusive
* @param endExclusive
* @return
*/
public static IntStream random(final int startInclusive, final int endExclusive) {
if (startInclusive >= endExclusive) {
throw new IllegalArgumentException("'startInclusive' must be less than 'endExclusive'");
}
final long mod = (long) endExclusive - (long) startInclusive;
if (mod < Integer.MAX_VALUE) {
final int n = (int) mod;
return generate(() -> RAND.nextInt(n) + startInclusive);
} else {
return generate(() -> (int) (Math.abs(RAND.nextLong() % mod) + startInclusive));
}
}
/**
*
*
* @param hasNext
* @param next
* @return
*/
public static IntStream iterate(final BooleanSupplier hasNext, final IntSupplier next) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(next);
return new IteratorIntStream(new IntIteratorEx() {
private boolean hasNextVal = false;
@Override
public boolean hasNext() {
if (!hasNextVal) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public int nextInt() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
hasNextVal = false;
return next.getAsInt();
}
});
}
/**
*
*
* @param init
* @param hasNext
* @param f
* @return
*/
public static IntStream iterate(final int init, final BooleanSupplier hasNext, final IntUnaryOperator f) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(f);
return new IteratorIntStream(new IntIteratorEx() {
private int t = 0;
private boolean isFirst = true;
private boolean hasNextVal = false;
@Override
public boolean hasNext() {
if (!hasNextVal) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public int nextInt() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
hasNextVal = false;
if (isFirst) {
isFirst = false;
t = init;
} else {
t = f.applyAsInt(t);
}
return t;
}
});
}
/**
*
* @param init
* @param hasNext test if has next by hasNext.test(init) for first time and hasNext.test(f.apply(previous)) for remaining.
* @param f
* @return
*/
public static IntStream iterate(final int init, final IntPredicate hasNext, final IntUnaryOperator f) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(f);
return new IteratorIntStream(new IntIteratorEx() {
private int t = 0;
private int cur = 0;
private boolean isFirst = true;
private boolean hasMore = true;
private boolean hasNextVal = false;
@Override
public boolean hasNext() {
if (!hasNextVal && hasMore) {
if (isFirst) {
isFirst = false;
hasNextVal = hasNext.test(cur = init);
} else {
hasNextVal = hasNext.test(cur = f.applyAsInt(t));
}
if (!hasNextVal) {
hasMore = false;
}
}
return hasNextVal;
}
@Override
public int nextInt() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
t = cur;
hasNextVal = false;
return t;
}
});
}
/**
*
*
* @param init
* @param f
* @return
*/
public static IntStream iterate(final int init, final IntUnaryOperator f) {
N.checkArgNotNull(f);
return new IteratorIntStream(new IntIteratorEx() {
private int t = 0;
private boolean isFirst = true;
@Override
public boolean hasNext() {
return true;
}
@Override
public int nextInt() {
if (isFirst) {
isFirst = false;
t = init;
} else {
t = f.applyAsInt(t);
}
return t;
}
});
}
/**
*
*
* @param s
* @return
*/
public static IntStream generate(final IntSupplier s) {
N.checkArgNotNull(s);
return new IteratorIntStream(new IntIteratorEx() {
@Override
public boolean hasNext() {
return true;
}
@Override
public int nextInt() {
return s.getAsInt();
}
});
}
/**
*
*
* @param
* @param source
* @param indexFunc
* @return
* @see #ofIndices(Object, int, int, BiFunction)
*/
public static IntStream ofIndices(final AC source, final BiFunction super AC, Integer, Integer> indexFunc) {
return ofIndices(source, 0, indexFunc);
}
/**
*
*
* @param
* @param source
* @param fromIndex
* @param indexFunc
* @return
* @see #ofIndices(Object, int, int, BiFunction)
*/
public static IntStream ofIndices(final AC source, final int fromIndex, final BiFunction super AC, Integer, Integer> indexFunc) {
return ofIndices(source, fromIndex, 1, indexFunc);
}
/**
*
*
* // Forwards:
* int[] a = {1, 2, 3, 2, 5, 1};
* IntStream.ofIndices(a, N::indexOf).println(); // [0, 5]
* IntStream.ofIndices(a, 1, N::indexOf).println(); // [5]
*
* // Backwards
* IntStream.ofIndices(a, 5, -1, N::lastIndexOf).println(); // [5, 0]
* IntStream.ofIndices(a, 4, -1, N::lastIndexOf).println(); // [0]
*
* // OR
* // Forwards:
* int[] source = { 1, 2, 3, 1, 2, 1 };
* int[] targetSubArray = { 1, 2 };
* IntStream.ofIndices(source, (a, fromIndex) -> Index.ofSubArray(a, fromIndex, targetSubArray, 0, targetSubArray.length).orElse(-1)).println(); // [0, 3]
*
* // Backwards
* IntStream.ofIndices(source, 5, -2, (a, fromIndex) -> Index.ofSubArray(a, fromIndex, targetSubArray, 0, targetSubArray.length).orElse(-1))
* .println(); // [3, 0]
*
*
*
* @param
* @param source
* @param fromIndex
* @param increment
* @param indexFunc
* @return
* @see #ofIndices(Object, int, int, BiFunction)
*/
public static IntStream ofIndices(final AC source, final int fromIndex, final int increment,
final BiFunction super AC, Integer, Integer> indexFunc) {
@SuppressWarnings("rawtypes")
final int sourceLen = source.getClass().isArray() ? Array.getLength(source)
: (source instanceof Collection ? ((Collection) source).size()
: (source instanceof CharSequence ? ((CharSequence) source).length() : Integer.MAX_VALUE));
return ofIndices(source, fromIndex, increment, sourceLen, indexFunc);
}
/**
*
*
* @param
* @param source
* @param fromIndex
* @param increment
* @param sourceLen
* @param indexFunc
* @return
*/
public static IntStream ofIndices(final AC source, final int fromIndex, final int increment, final int sourceLen,
final BiFunction super AC, Integer, Integer> indexFunc) {
N.checkArgNotNegative(fromIndex, "fromIndex");
N.checkArgument(increment != 0, "'increment' can't be zero");
N.checkArgNotNull(indexFunc, "indexFunc");
if (source == null) {
return IntStream.empty();
}
final IntUnaryOperator f = idx -> ((increment > 0 && idx >= sourceLen - increment) || (increment < 0 && idx + increment < 0)) ? N.INDEX_NOT_FOUND
: indexFunc.apply(source, idx + increment);
return iterate(indexFunc.apply(source, fromIndex), com.landawn.abacus.util.function.IntPredicate.NOT_NEGATIVE, f);
}
/**
*
*
* @param a
* @return
*/
@SafeVarargs
public static IntStream concat(final int[]... a) {
if (N.isEmpty(a)) {
return empty();
}
return concat(Arrays.asList(a));
}
/**
*
*
* @param a
* @return
*/
@SafeVarargs
public static IntStream concat(final IntIterator... a) {
if (N.isEmpty(a)) {
return empty();
}
return concatIterators(Array.asList(a));
}
/**
*
*
* @param a
* @return
*/
@SafeVarargs
public static IntStream concat(final IntStream... a) {
if (N.isEmpty(a)) {
return empty();
}
return concat(Array.asList(a));
}
/**
*
*
* @param c
* @return
*/
@Beta
public static IntStream concat(final List c) {
if (N.isEmpty(c)) {
return empty();
}
return of(new IntIteratorEx() {
private final Iterator iter = c.iterator();
private int[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public int nextInt() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return cur[cursor++];
}
});
}
/**
*
*
* @param c
* @return
*/
public static IntStream concat(final Collection extends IntStream> c) {
return N.isEmpty(c) ? empty() : new IteratorIntStream(new IntIteratorEx() { //NOSONAR
private final Iterator extends IntStream> iterators = c.iterator();
private IntStream cur;
private IntIterator iter;
@Override
public boolean hasNext() {
while ((iter == null || !iter.hasNext()) && iterators.hasNext()) {
if (cur != null) {
cur.close();
}
cur = iterators.next();
iter = cur == null ? null : cur.iteratorEx();
}
return iter != null && iter.hasNext();
}
@Override
public int nextInt() {
if ((iter == null || !iter.hasNext()) && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return iter.nextInt();
}
}).onClose(newCloseHandler(c));
}
/**
*
*
* @param c
* @return
*/
@Beta
public static IntStream concatIterators(final Collection extends IntIterator> c) {
if (N.isEmpty(c)) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private final Iterator extends IntIterator> iter = c.iterator();
private IntIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public int nextInt() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return cur.nextInt();
}
});
}
/**
* Zip together the "a" and "b" arrays until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param zipFunction
* @return
*/
public static IntStream zip(final int[] a, final int[] b, final IntBinaryOperator zipFunction) {
if (N.isEmpty(a) || N.isEmpty(b)) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private final int len = N.min(N.len(a), N.len(b));
private int cursor = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public int nextInt() {
if (cursor >= len) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return zipFunction.applyAsInt(a[cursor], b[cursor++]);
}
});
}
/**
* Zip together the "a", "b" and "c" arrays until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param zipFunction
* @return
*/
public static IntStream zip(final int[] a, final int[] b, final int[] c, final IntTernaryOperator zipFunction) {
if (N.isEmpty(a) || N.isEmpty(b) || N.isEmpty(c)) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private final int len = N.min(N.len(a), N.len(b), N.len(c));
private int cursor = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public int nextInt() {
if (cursor >= len) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
return zipFunction.applyAsInt(a[cursor], b[cursor], c[cursor++]);
}
});
}
/**
* Zip together the "a" and "b" iterators until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param zipFunction
* @return
*/
public static IntStream zip(final IntIterator a, final IntIterator b, final IntBinaryOperator zipFunction) {
return new IteratorIntStream(new IntIteratorEx() {
private final IntIterator iterA = a == null ? IntIterator.empty() : a;
private final IntIterator iterB = b == null ? IntIterator.empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext();
}
@Override
public int nextInt() {
return zipFunction.applyAsInt(iterA.nextInt(), iterB.nextInt());
}
});
}
/**
* Zip together the "a", "b" and "c" iterators until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param zipFunction
* @return
*/
public static IntStream zip(final IntIterator a, final IntIterator b, final IntIterator c, final IntTernaryOperator zipFunction) {
return new IteratorIntStream(new IntIteratorEx() {
private final IntIterator iterA = a == null ? IntIterator.empty() : a;
private final IntIterator iterB = b == null ? IntIterator.empty() : b;
private final IntIterator iterC = c == null ? IntIterator.empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public int nextInt() {
return zipFunction.applyAsInt(iterA.nextInt(), iterB.nextInt(), iterC.nextInt());
}
});
}
/**
* Zip together the "a" and "b" streams until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param zipFunction
* @return
*/
public static IntStream zip(final IntStream a, final IntStream b, final IntBinaryOperator zipFunction) {
return zip(iterate(a), iterate(b), zipFunction).onClose(newCloseHandler(a, b));
}
/**
* Zip together the "a", "b" and "c" streams until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param zipFunction
* @return
*/
public static IntStream zip(final IntStream a, final IntStream b, final IntStream c, final IntTernaryOperator zipFunction) {
return zip(iterate(a), iterate(b), iterate(c), zipFunction).onClose(newCloseHandler(Array.asList(a, b, c)));
}
/**
* Zip together the iterators until one of them runs out of values.
* Each array of values is combined into a single value using the supplied zipFunction function.
*
* @param c
* @param zipFunction
* @return
*/
public static IntStream zip(final Collection extends IntStream> c, final IntNFunction zipFunction) {
return Stream.zip(c, zipFunction).mapToInt(com.landawn.abacus.util.function.ToIntFunction.UNBOX);
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static IntStream zip(final int[] a, final int[] b, final int valueForNoneA, final int valueForNoneB, final IntBinaryOperator zipFunction) {
if (N.isEmpty(a) && N.isEmpty(b)) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private final int aLen = N.len(a), bLen = N.len(b), len = N.max(aLen, bLen);
private int cursor = 0;
private int ret = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public int nextInt() {
if (cursor >= len) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
ret = zipFunction.applyAsInt(cursor < aLen ? a[cursor] : valueForNoneA, cursor < bLen ? b[cursor] : valueForNoneB);
cursor++;
return ret;
}
});
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static IntStream zip(final int[] a, final int[] b, final int[] c, final int valueForNoneA, final int valueForNoneB, final int valueForNoneC,
final IntTernaryOperator zipFunction) {
if (N.isEmpty(a) && N.isEmpty(b) && N.isEmpty(c)) {
return empty();
}
return new IteratorIntStream(new IntIteratorEx() {
private final int aLen = N.len(a), bLen = N.len(b), cLen = N.len(c), len = N.max(aLen, bLen, cLen);
private int cursor = 0;
private int ret = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public int nextInt() {
if (cursor >= len) {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
ret = zipFunction.applyAsInt(cursor < aLen ? a[cursor] : valueForNoneA, cursor < bLen ? b[cursor] : valueForNoneB,
cursor < cLen ? c[cursor] : valueForNoneC);
cursor++;
return ret;
}
});
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static IntStream zip(final IntIterator a, final IntIterator b, final int valueForNoneA, final int valueForNoneB,
final IntBinaryOperator zipFunction) {
return new IteratorIntStream(new IntIteratorEx() {
private final IntIterator iterA = a == null ? IntIterator.empty() : a;
private final IntIterator iterB = b == null ? IntIterator.empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext();
}
@Override
public int nextInt() {
if (iterA.hasNext()) {
return zipFunction.applyAsInt(iterA.nextInt(), iterB.hasNext() ? iterB.nextInt() : valueForNoneB);
} else {
return zipFunction.applyAsInt(valueForNoneA, iterB.nextInt());
}
}
});
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static IntStream zip(final IntIterator a, final IntIterator b, final IntIterator c, final int valueForNoneA, final int valueForNoneB,
final int valueForNoneC, final IntTernaryOperator zipFunction) {
return new IteratorIntStream(new IntIteratorEx() {
private final IntIterator iterA = a == null ? IntIterator.empty() : a;
private final IntIterator iterB = b == null ? IntIterator.empty() : b;
private final IntIterator iterC = c == null ? IntIterator.empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext() || iterC.hasNext();
}
@Override
public int nextInt() {
if (iterA.hasNext()) {
return zipFunction.applyAsInt(iterA.nextInt(), iterB.hasNext() ? iterB.nextInt() : valueForNoneB,
iterC.hasNext() ? iterC.nextInt() : valueForNoneC);
} else if (iterB.hasNext()) {
return zipFunction.applyAsInt(valueForNoneA, iterB.nextInt(), iterC.hasNext() ? iterC.nextInt() : valueForNoneC);
} else {
return zipFunction.applyAsInt(valueForNoneA, valueForNoneB, iterC.nextInt());
}
}
});
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static IntStream zip(final IntStream a, final IntStream b, final int valueForNoneA, final int valueForNoneB, final IntBinaryOperator zipFunction) {
return zip(iterate(a), iterate(b), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(a, b));
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static IntStream zip(final IntStream a, final IntStream b, final IntStream c, final int valueForNoneA, final int valueForNoneB,
final int valueForNoneC, final IntTernaryOperator zipFunction) {
return zip(iterate(a), iterate(b), iterate(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction)
.onClose(newCloseHandler(Array.asList(a, b, c)));
}
/**
* Zip together the iterators until all of them runs out of values.
* Each array of values is combined into a single value using the supplied zipFunction function.
*
* @param c
* @param valuesForNone value to fill for any iterator runs out of values.
* @param zipFunction
* @return
*/
public static IntStream zip(final Collection extends IntStream> c, final int[] valuesForNone, final IntNFunction zipFunction) {
return Stream.zip(c, valuesForNone, zipFunction).mapToInt(com.landawn.abacus.util.function.ToIntFunction.UNBOX);
}
/**
*
* @param a
* @param b
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final int[] a, final int[] b, final IntBiFunction nextSelector) {
if (N.isEmpty(a)) {
return of(b);
} else if (N.isEmpty(b)) {
return of(a);
}
return new IteratorIntStream(new IntIteratorEx() {
private final int lenA = a.length;
private final int lenB = b.length;
private int cursorA = 0;
private int cursorB = 0;
@Override
public boolean hasNext() {
return cursorA < lenA || cursorB < lenB;
}
@Override
public int nextInt() {
if (cursorA < lenA) {
if (cursorB < lenB) {
if (nextSelector.apply(a[cursorA], b[cursorB]) == MergeResult.TAKE_FIRST) {
return a[cursorA++];
} else {
return b[cursorB++];
}
} else {
return a[cursorA++];
}
} else if (cursorB < lenB) {
return b[cursorB++];
} else {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
}
});
}
/**
*
* @param a
* @param b
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final int[] a, final int[] b, final int[] c, final IntBiFunction nextSelector) {
return merge(merge(a, b, nextSelector).iteratorEx(), IntStream.of(c).iteratorEx(), nextSelector);
}
/**
*
* @param a
* @param b
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final IntIterator a, final IntIterator b, final IntBiFunction nextSelector) {
return new IteratorIntStream(new IntIteratorEx() {
private final IntIterator iterA = a == null ? IntIterator.empty() : a;
private final IntIterator iterB = b == null ? IntIterator.empty() : b;
private int nextA = 0;
private int nextB = 0;
private boolean hasNextA = false;
private boolean hasNextB = false;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext() || hasNextA || hasNextB;
}
@Override
public int nextInt() {
if (hasNextA) {
if (iterB.hasNext()) {
if (nextSelector.apply(nextA, (nextB = iterB.nextInt())) == MergeResult.TAKE_FIRST) {
hasNextA = false;
hasNextB = true;
return nextA;
} else {
return nextB;
}
} else {
hasNextA = false;
return nextA;
}
} else if (hasNextB) {
if (iterA.hasNext()) {
if (nextSelector.apply((nextA = iterA.nextInt()), nextB) == MergeResult.TAKE_FIRST) {
return nextA;
} else {
hasNextA = true;
hasNextB = false;
return nextB;
}
} else {
hasNextB = false;
return nextB;
}
} else if (iterA.hasNext()) {
if (iterB.hasNext()) {
if (nextSelector.apply((nextA = iterA.nextInt()), (nextB = iterB.nextInt())) == MergeResult.TAKE_FIRST) {
hasNextB = true;
return nextA;
} else {
hasNextA = true;
return nextB;
}
} else {
return iterA.nextInt();
}
} else if (iterB.hasNext()) {
return iterB.nextInt();
} else {
throw new NoSuchElementException(ERROR_MSG_FOR_NO_SUCH_EX);
}
}
});
}
/**
*
* @param a
* @param b
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final IntIterator a, final IntIterator b, final IntIterator c, final IntBiFunction nextSelector) {
return merge(merge(a, b, nextSelector).iteratorEx(), c, nextSelector);
}
/**
*
* @param a
* @param b
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final IntStream a, final IntStream b, final IntBiFunction nextSelector) {
return merge(iterate(a), iterate(b), nextSelector).onClose(newCloseHandler(a, b));
}
/**
*
* @param a
* @param b
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final IntStream a, final IntStream b, final IntStream c, final IntBiFunction nextSelector) {
return merge(merge(a, b, nextSelector), c, nextSelector);
}
/**
*
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream merge(final Collection extends IntStream> c, final IntBiFunction nextSelector) {
if (N.isEmpty(c)) {
return empty();
} else if (c.size() == 1) {
return c.iterator().next();
} else if (c.size() == 2) {
final Iterator extends IntStream> iter = c.iterator();
return merge(iter.next(), iter.next(), nextSelector);
}
final Iterator extends IntStream> iter = c.iterator();
IntStream result = merge(iter.next(), iter.next(), nextSelector);
while (iter.hasNext()) {
result = merge(result, iter.next(), nextSelector);
}
return result;
}
/**
* All the elements from each input {@code Collection/Iterator/Stream} will be merged into two queues by multiple threads.
* Then these two new queues will be merged into one {@code Iterator/Stream} by one thread.
* So it's not totally lazy evaluation and may cause out of memory error if there are too many elements merged into the new queues.
* Consider using {@code merge}, which is totally lazy evaluation.
*
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static IntStream parallelMerge(final Collection extends IntStream> c, final IntBiFunction nextSelector) {
return parallelMerge(c, nextSelector, DEFAULT_MAX_THREAD_NUM);
}
/**
* All the elements from each input {@code Collection/Iterator/Stream} will be merged into two queues by multiple threads.
* Then these two new queues will be merged into one {@code Iterator/Stream} by one thread.
* So it's not totally lazy evaluation and may cause out of memory error if there are too many elements merged into the new queues.
* Consider using {@code merge}, which is totally lazy evaluation.
*
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @param maxThreadNum
* @return
*/
public static IntStream parallelMerge(final Collection extends IntStream> c, final IntBiFunction nextSelector, final int maxThreadNum) {
N.checkArgument(maxThreadNum > 0, "'maxThreadNum' must not less than 1");
if (maxThreadNum <= 1) {
return merge(c, nextSelector);
} else if (N.isEmpty(c)) {
return empty();
} else if (c.size() == 1) {
return c.iterator().next();
} else if (c.size() == 2) {
final Iterator extends IntStream> iter = c.iterator();
return merge(iter.next(), iter.next(), nextSelector);
} else if (c.size() == 3) {
final Iterator extends IntStream> iter = c.iterator();
return merge(iter.next(), iter.next(), iter.next(), nextSelector);
}
final Supplier supplier = () -> {
final Queue queue = N.newLinkedList();
queue.addAll(c);
final Holder eHolder = new Holder<>();
final MutableInt cnt = MutableInt.of(c.size());
final List> futureList = new ArrayList<>(c.size() - 1);
final int threadNum = N.min(maxThreadNum, c.size() / 2 + 1);
AsyncExecutor asyncExecutorToUse = checkAsyncExecutor(DEFAULT_ASYNC_EXECUTOR, threadNum, 0);
for (int i = 0; i < threadNum; i++) {
asyncExecutorToUse = execute(asyncExecutorToUse, threadNum, 0, i, futureList, () -> {
IntStream a = null;
IntStream b = null;
IntStream c1 = null;
try {
while (eHolder.value() == null) {
synchronized (queue) {
if (cnt.intValue() > 2 && queue.size() > 1) {
a = queue.poll();
b = queue.poll();
cnt.decrement();
} else {
break;
}
}
c1 = IntStream.of(merge(a, b, nextSelector).toArray());
synchronized (queue) {
queue.offer(c1);
}
}
} catch (Throwable e) {
setError(eHolder, e);
}
});
}
completeAndShutdownTempExecutor(futureList, eHolder, c, asyncExecutorToUse);
return merge(queue.poll(), queue.poll(), nextSelector);
};
return Stream.just(supplier).flatMapToInt(Supplier::get);
}
public abstract static class IntStreamEx extends IntStream {
private IntStreamEx(boolean sorted, Collection closeHandlers) { //NOSONAR
super(sorted, closeHandlers);
// Factory class.
}
}
}