com.landawn.abacus.util.stream.DoubleStream 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.DoubleBuffer;
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.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleSupplier;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.ObjDoubleConsumer;
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.DoubleIterator;
import com.landawn.abacus.util.DoubleList;
import com.landawn.abacus.util.DoubleSummaryStatistics;
import com.landawn.abacus.util.Fn.FnD;
import com.landawn.abacus.util.Holder;
import com.landawn.abacus.util.IndexedDouble;
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.Throwables;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.function.DoubleBiFunction;
import com.landawn.abacus.util.function.DoubleBiPredicate;
import com.landawn.abacus.util.function.DoubleMapMultiConsumer;
import com.landawn.abacus.util.function.DoubleNFunction;
import com.landawn.abacus.util.function.DoubleTernaryOperator;
import com.landawn.abacus.util.function.DoubleToFloatFunction;
import com.landawn.abacus.util.function.DoubleTriPredicate;
/**
* 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 DoubleStream
extends StreamBase {
static final Random RAND = new SecureRandom();
DoubleStream(final boolean sorted, final Collection closeHandlers) {
super(sorted, null, closeHandlers);
}
@Override
public DoubleStream rateLimited(final RateLimiter rateLimiter) {
checkArgNotNull(rateLimiter, "rateLimiter");
final DoubleConsumer action = it -> rateLimiter.acquire();
if (isParallel()) {
return sequential().onEach(action).parallel(maxThreadNum(), executorNumForVirtualThread(), splitor(), asyncExecutor(), cancelUncompletedThreads());
} else {
return onEach(action);
}
}
@Override
public DoubleStream skipUntil(final DoublePredicate predicate) {
assertNotClosed();
return dropWhile(t -> !predicate.test(t));
}
@ParallelSupported
@IntermediateOp
public abstract DoubleStream map(DoubleUnaryOperator mapper);
@ParallelSupported
@IntermediateOp
public abstract IntStream mapToInt(DoubleToIntFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract LongStream mapToLong(DoubleToLongFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract FloatStream mapToFloat(DoubleToFloatFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract Stream mapToObj(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream flatMap(DoubleFunction mapper);
// public abstract DoubleStream flatmap(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream flatmap(DoubleFunction mapper); //NOSONAR
@ParallelSupported
@IntermediateOp
public abstract IntStream flatMapToInt(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract LongStream flatMapToLong(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract FloatStream flatMapToFloat(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract Stream flatMapToObj(DoubleFunction> mapper);
@ParallelSupported
@IntermediateOp
public abstract Stream flatmapToObj(DoubleFunction> mapper); //NOSONAR
@ParallelSupported
@IntermediateOp
public abstract Stream flattMapToObj(DoubleFunction mapper);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream mapMulti(DoubleMapMultiConsumer mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
* @param
* @param mapper
* @return
*/
@Beta
@ParallelSupported
@IntermediateOp
public abstract DoubleStream mapPartial(DoubleFunction mapper);
/**
* Note: copied from StreamEx: https://github.com/amaembo/streamex
*
* @param
* @param mapper
* @return
*/
@Beta
@ParallelSupported
@IntermediateOp
public abstract DoubleStream mapPartialJdk(DoubleFunction 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(DoubleBiPredicate, DoubleBinaryOperator)
* @see Stream#rangeMap(BiPredicate, BiFunction)
*/
@SequentialOnly
@IntermediateOp
public abstract DoubleStream rangeMap(final DoubleBiPredicate sameRange, final DoubleBinaryOperator 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 Stream#rangeMap(BiPredicate, BiFunction)
*/
@SequentialOnly
@IntermediateOp
public abstract Stream rangeMapToObj(final DoubleBiPredicate sameRange, final DoubleBiFunction 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 DoubleBiPredicate 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 DoubleStream collapse(final DoubleBiPredicate collapsible, final DoubleBinaryOperator 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 DoubleStream collapse(final DoubleTriPredicate collapsible, final DoubleBinaryOperator 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 DoubleStream scan(final DoubleBinaryOperator 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 DoubleStream scan(final double init, final DoubleBinaryOperator accumulator);
/**
*
* @param init
* @param accumulator
* @param initIncluded
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract DoubleStream scan(final double init, final DoubleBinaryOperator accumulator, final boolean initIncluded);
@SequentialOnly
@IntermediateOp
public abstract DoubleStream prepend(final double... a);
@SequentialOnly
@IntermediateOp
public abstract DoubleStream append(final double... a);
@SequentialOnly
@IntermediateOp
public abstract DoubleStream appendIfEmpty(final double... a);
/**
*
* This method only runs sequentially, even in parallel stream.
*
* @param n
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract DoubleStream top(int n);
/**
*
* This method only runs sequentially, even in parallel stream.
*
* @param n
* @param comparator
* @return
*/
@SequentialOnly
@IntermediateOp
public abstract DoubleStream top(final int n, Comparator comparator);
@SequentialOnly
@TerminalOp
public abstract DoubleList toDoubleList();
/**
*
* @param keyMapper
* @param valueMapper
* @return
* @see Collectors#toMap(Throwables.Function, Throwables.Function)
*/
@ParallelSupported
@TerminalOp
public abstract Map toMap(Throwables.DoubleFunction keyMapper,
Throwables.DoubleFunction valueMapper) throws E, E2;
/**
*
* @param keyMapper
* @param valueMapper
* @param mapFactory
* @return
* @see Collectors#toMap(Throwables.Function, Throwables.Function, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception, E2 extends Exception> M toMap(Throwables.DoubleFunction keyMapper,
Throwables.DoubleFunction valueMapper, Supplier mapFactory) throws E, E2;
/**
*
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @return
* @see Collectors#toMap(Throwables.Function, Throwables.Function, BinaryOperator)
*/
@ParallelSupported
@TerminalOp
public abstract Map toMap(Throwables.DoubleFunction keyMapper,
Throwables.DoubleFunction valueMapper, BinaryOperator mergeFunction) throws E, E2;
/**
*
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @param mapFactory
* @return
* @see Collectors#toMap(Throwables.Function, Throwables.Function, BinaryOperator, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception, E2 extends Exception> M toMap(Throwables.DoubleFunction keyMapper,
Throwables.DoubleFunction valueMapper, BinaryOperator mergeFunction, Supplier mapFactory) throws E, E2;
/**
*
* @param keyMapper
* @param downstream
* @return
* @see Collectors#groupingBy(Throwables.Function, Collector)
*/
@ParallelSupported
@TerminalOp
public abstract Map groupTo(Throwables.DoubleFunction keyMapper,
final Collector downstream) throws E;
/**
*
* @param keyMapper
* @param downstream
* @param mapFactory
* @return
* @see Collectors#groupingBy(Throwables.Function, Collector, Supplier)
*/
@ParallelSupported
@TerminalOp
public abstract , E extends Exception> M groupTo(Throwables.DoubleFunction keyMapper,
final Collector downstream, final Supplier mapFactory) throws E;
@ParallelSupported
@TerminalOp
public abstract double reduce(double identity, DoubleBinaryOperator op);
@ParallelSupported
@TerminalOp
public abstract OptionalDouble reduce(DoubleBinaryOperator op);
/**
*
* @param
* @param supplier
* @param accumulator
* @param combiner
* @return
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@ParallelSupported
@TerminalOp
public abstract R collect(Supplier supplier, ObjDoubleConsumer 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, ObjDoubleConsumer, BiConsumer)}.
*
* @param supplier
* @param accumulator
* @return
* @see #collect(Supplier, ObjDoubleConsumer, BiConsumer)
* @see Stream#collect(Supplier, BiConsumer)
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
@ParallelSupported
@TerminalOp
public abstract R collect(Supplier supplier, ObjDoubleConsumer accumulator);
@ParallelSupported
@TerminalOp
public abstract void forEach(final Throwables.DoubleConsumer action) throws E;
@ParallelSupported
@TerminalOp
public abstract void forEachIndexed(Throwables.IndexedDoubleConsumer action) throws E;
@ParallelSupported
@TerminalOp
public abstract boolean anyMatch(final Throwables.DoublePredicate predicate) throws E;
@ParallelSupported
@TerminalOp
public abstract boolean allMatch(final Throwables.DoublePredicate predicate) throws E;
@ParallelSupported
@TerminalOp
public abstract boolean noneMatch(final Throwables.DoublePredicate predicate) throws E;
@ParallelSupported
@TerminalOp
public abstract OptionalDouble findFirst(final Throwables.DoublePredicate 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 OptionalDouble} will be returned.
*
* @param
* @param predicateForFirst
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalDouble findFirstOrAny(Throwables.DoublePredicate 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 OptionalDouble} will be returned.
*
* @param
* @param predicateForFirst
* @return
* @throws E
*/
@ParallelSupported
@TerminalOp
public abstract OptionalDouble findFirstOrLast(Throwables.DoublePredicate 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 OptionalDouble findLast(final Throwables.DoublePredicate predicate) throws E;
@ParallelSupported
@TerminalOp
public abstract OptionalDouble findAny(final Throwables.DoublePredicate predicate) throws E;
@SequentialOnly
@TerminalOp
public abstract OptionalDouble min();
@SequentialOnly
@TerminalOp
public abstract OptionalDouble 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 OptionalDouble kthLargest(int k);
@SequentialOnly
@TerminalOp
public abstract double sum();
@SequentialOnly
@TerminalOp
public abstract OptionalDouble average();
@SequentialOnly
@TerminalOp
public abstract DoubleSummaryStatistics summarize();
@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(DoubleStream, DoubleBiFunction)}
// * @see #mergeWith(DoubleStream, DoubleBiFunction)
// */
// @SequentialOnly
// @IntermediateOp
// @Deprecated
// public DoubleStream merge(final DoubleStream b, final DoubleBiFunction 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 DoubleStream mergeWith(final DoubleStream b, final DoubleBiFunction nextSelector);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream zipWith(DoubleStream b, DoubleBinaryOperator zipFunction);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream zipWith(DoubleStream b, DoubleStream c, DoubleTernaryOperator zipFunction);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream zipWith(DoubleStream b, double valueForNoneA, double valueForNoneB, DoubleBinaryOperator zipFunction);
@ParallelSupported
@IntermediateOp
public abstract DoubleStream zipWith(DoubleStream b, DoubleStream c, double valueForNoneA, double valueForNoneB, double valueForNoneC,
DoubleTernaryOperator zipFunction);
@SequentialOnly
@IntermediateOp
public abstract java.util.stream.DoubleStream 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 DoubleStream sjps(Function op) {
// if (this.isParallel()) {
// return of(op.apply(this.toJdkStream())).sequential();
// } else {
// return of(op.apply(this.toJdkStream().parallel()));
// }
// }
@SequentialOnly
@IntermediateOp
public abstract Stream boxed();
/**
* Remember to close this Stream after the iteration is done, if needed.
*
* @return
*/
@Override
public DoubleIterator iterator() {
assertNotClosed();
if (!isEmptyCloseHandlers(closeHandlers) && logger.isWarnEnabled()) {
logger.warn("### Remember to close " + ClassUtil.getSimpleClassName(getClass()));
}
return iteratorEx();
}
abstract DoubleIteratorEx iteratorEx();
public static DoubleStream empty() {
return new ArrayDoubleStream(N.EMPTY_DOUBLE_ARRAY, true, null);
}
public static DoubleStream ofNullable(final Double e) {
return e == null ? empty() : of(e);
}
@SafeVarargs
public static DoubleStream of(final double... a) {
return N.isNullOrEmpty(a) ? empty() : new ArrayDoubleStream(a);
}
public static DoubleStream of(final double[] a, final int startIndex, final int endIndex) {
return N.isNullOrEmpty(a) && (startIndex == 0 && endIndex == 0) ? empty() : new ArrayDoubleStream(a, startIndex, endIndex);
}
public static DoubleStream of(final Double[] a) {
return Stream.of(a).mapToDouble(FnD.unbox());
}
public static DoubleStream of(final Double[] a, final int startIndex, final int endIndex) {
return Stream.of(a, startIndex, endIndex).mapToDouble(FnD.unbox());
}
public static DoubleStream of(final Collection c) {
return Stream.of(c).mapToDouble(FnD.unbox());
}
public static DoubleStream of(final DoubleIterator iterator) {
return iterator == null ? empty() : new IteratorDoubleStream(iterator);
}
public static DoubleStream of(final java.util.stream.DoubleStream stream) {
if (stream == null) {
return empty();
}
return of(new DoubleIteratorEx() {
private PrimitiveIterator.OfDouble iter = null;
@Override
public boolean hasNext() {
if (iter == null) {
iter = stream.iterator();
}
return iter.hasNext();
}
@Override
public double nextDouble() {
if (iter == null) {
iter = stream.iterator();
}
return iter.nextDouble();
}
@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 double[] toArray() {
return iter == null ? stream.toArray() : super.toArray();
}
}).__(s -> stream.isParallel() ? s.parallel() : s.sequential()).onClose(stream::close);
}
public static DoubleStream of(final DoubleBuffer buf) {
if (buf == null) {
return empty();
}
return IntStream.range(buf.position(), buf.limit()).mapToDouble(buf::get);
}
public static DoubleStream of(final OptionalDouble op) {
return op == null || !op.isPresent() ? DoubleStream.empty() : DoubleStream.of(op.get());
}
public static DoubleStream of(final java.util.OptionalDouble op) {
return op == null || !op.isPresent() ? DoubleStream.empty() : DoubleStream.of(op.getAsDouble());
}
/**
* Lazy evaluation.
*
*
* This is equal to: {@code Stream.just(supplier).flatMapToDouble(it -> it.get())}.
*
* @param
* @param supplier
* @return
*/
public static DoubleStream defer(final Supplier supplier) {
N.checkArgNotNull(supplier, "supplier");
return Stream.just(supplier).flatMapToDouble(Supplier::get);
}
// /**
// * Lazy evaluation.
// *
// *
// * This is equal to: {@code Stream.just(supplier).flatMapToDouble(it -> it.get().stream())}.
// *
// * @param supplier
// * @return
// */
// @Beta
// public static DoubleStream from(final Supplier supplier) {
// N.checkArgNotNull(supplier, "supplier");
//
// return Stream.just(supplier).flatMapToDouble(it -> it.get().stream());
// }
private static final Function flatMapper = DoubleStream::of;
private static final Function flattMapper = DoubleStream::flatten;
public static DoubleStream flatten(final double[][] a) {
return N.isNullOrEmpty(a) ? empty() : Stream.of(a).flatMapToDouble(flatMapper);
}
public static DoubleStream flatten(final double[][] a, final boolean vertically) {
if (N.isNullOrEmpty(a)) {
return empty();
} else if (a.length == 1) {
return of(a[0]);
} else if (!vertically) {
return Stream.of(a).flatMapToDouble(flatMapper);
}
long n = 0;
for (double[] e : a) {
n += N.len(e);
}
if (n == 0) {
return empty();
}
final int rows = N.len(a);
final long count = n;
final DoubleIterator iter = new DoubleIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public double nextDouble() {
if (cnt++ >= count) {
throw new NoSuchElementException();
}
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);
}
public static DoubleStream flatten(final double[][] a, final double valueForNone, final boolean vertically) {
if (N.isNullOrEmpty(a)) {
return empty();
} else if (a.length == 1) {
return of(a[0]);
}
long n = 0;
int maxLen = 0;
for (double[] 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;
DoubleIterator iter = null;
if (vertically) {
iter = new DoubleIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public double nextDouble() {
if (cnt++ >= count) {
throw new NoSuchElementException();
}
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 DoubleIteratorEx() {
private int rowNum = 0;
private int colNum = 0;
private long cnt = 0;
@Override
public boolean hasNext() {
return cnt < count;
}
@Override
public double nextDouble() {
if (cnt++ >= count) {
throw new NoSuchElementException();
}
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);
}
public static DoubleStream flatten(final double[][][] a) {
return N.isNullOrEmpty(a) ? empty() : Stream.of(a).flatMapToDouble(flattMapper);
}
/**
*
* @param a
* @return
* @deprecated
*/
@Deprecated
@Beta
@SafeVarargs
public static DoubleStream from(final float... a) {
return N.isNullOrEmpty(a) ? empty() : from(a, 0, a.length);
}
/**
*
* @param a
* @param fromIndex
* @param toIndex
* @return
* @deprecated
*/
@Deprecated
@Beta
public static DoubleStream from(final float[] a, final int fromIndex, final int toIndex) {
N.checkFromToIndex(fromIndex, toIndex, N.len(a));
if (fromIndex == toIndex) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
private int cursor = fromIndex;
@Override
public boolean hasNext() {
return cursor < toIndex;
}
@Override
public double nextDouble() {
if (cursor >= toIndex) {
throw new NoSuchElementException();
}
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 double[] toArray() {
final double[] result = new double[toIndex - cursor];
for (int i = cursor; i < toIndex; i++) {
result[i - cursor] = a[i];
}
return result;
}
});
}
public static DoubleStream repeat(final double 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 IteratorDoubleStream(new DoubleIteratorEx() {
private long cnt = n;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public double nextDouble() {
if (cnt-- <= 0) {
throw new NoSuchElementException();
}
return element;
}
@Override
public void advance(long n) {
cnt = n >= cnt ? 0 : cnt - (int) n;
}
@Override
public long count() {
return cnt;
}
@Override
public double[] toArray() {
final double[] result = new double[(int) cnt];
for (int i = 0; i < cnt; i++) {
result[i] = element;
}
cnt = 0;
return result;
}
});
}
public static DoubleStream random() {
return generate(RAND::nextDouble);
}
public static DoubleStream iterate(final BooleanSupplier hasNext, final DoubleSupplier next) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(next);
return new IteratorDoubleStream(new DoubleIteratorEx() {
private boolean hasNextVal = false;
@Override
public boolean hasNext() {
if (!hasNextVal) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public double nextDouble() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException();
}
hasNextVal = false;
return next.getAsDouble();
}
});
}
public static DoubleStream iterate(final double init, final BooleanSupplier hasNext, final DoubleUnaryOperator f) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(f);
return new IteratorDoubleStream(new DoubleIteratorEx() {
private double t = 0;
private boolean isFirst = true;
private boolean hasNextVal = false;
@Override
public boolean hasNext() {
if (!hasNextVal) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public double nextDouble() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException();
}
hasNextVal = false;
if (isFirst) {
isFirst = false;
t = init;
} else {
t = f.applyAsDouble(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 DoubleStream iterate(final double init, final DoublePredicate hasNext, final DoubleUnaryOperator f) {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(f);
return new IteratorDoubleStream(new DoubleIteratorEx() {
private double t = 0;
private double 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.applyAsDouble(t));
}
if (!hasNextVal) {
hasMore = false;
}
}
return hasNextVal;
}
@Override
public double nextDouble() {
if (!hasNextVal && !hasNext()) {
throw new NoSuchElementException();
}
t = cur;
hasNextVal = false;
return t;
}
});
}
public static DoubleStream iterate(final double init, final DoubleUnaryOperator f) {
N.checkArgNotNull(f);
return new IteratorDoubleStream(new DoubleIteratorEx() {
private double t = 0;
private boolean isFirst = true;
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
if (isFirst) {
isFirst = false;
t = init;
} else {
t = f.applyAsDouble(t);
}
return t;
}
});
}
public static DoubleStream generate(final DoubleSupplier s) {
N.checkArgNotNull(s);
return new IteratorDoubleStream(new DoubleIteratorEx() {
@Override
public boolean hasNext() {
return true;
}
@Override
public double nextDouble() {
return s.getAsDouble();
}
});
}
@SafeVarargs
public static DoubleStream concat(final double[]... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return concat(Arrays.asList(a));
}
@SafeVarargs
public static DoubleStream concat(final DoubleIterator... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return concatIterators(Array.asList(a));
}
@SafeVarargs
public static DoubleStream concat(final DoubleStream... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return concat(Array.asList(a));
}
@Beta
public static DoubleStream concat(final List c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
return of(new DoubleIteratorEx() {
private final Iterator iter = c.iterator();
private double[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public double nextDouble() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
});
}
public static DoubleStream concat(final Collection c) {
return N.isNullOrEmpty(c) ? empty() : new IteratorDoubleStream(new DoubleIteratorEx() { //NOSONAR
private final Iterator iterators = c.iterator();
private DoubleStream cur;
private DoubleIterator 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 double nextDouble() {
if ((iter == null || !iter.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return iter.nextDouble();
}
}).onClose(newCloseHandler(c));
}
@Beta
public static DoubleStream concatIterators(final Collection c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final Iterator iter = c.iterator();
private DoubleIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public double nextDouble() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextDouble();
}
});
}
/**
* 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
* @return
*/
public static DoubleStream zip(final double[] a, final double[] b, final DoubleBinaryOperator zipFunction) {
if (N.isNullOrEmpty(a) || N.isNullOrEmpty(b)) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
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 double nextDouble() {
if (cursor >= len) {
throw new NoSuchElementException();
}
return zipFunction.applyAsDouble(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
* @return
*/
public static DoubleStream zip(final double[] a, final double[] b, final double[] c, final DoubleTernaryOperator zipFunction) {
if (N.isNullOrEmpty(a) || N.isNullOrEmpty(b) || N.isNullOrEmpty(c)) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
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 double nextDouble() {
if (cursor >= len) {
throw new NoSuchElementException();
}
return zipFunction.applyAsDouble(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
* @return
*/
public static DoubleStream zip(final DoubleIterator a, final DoubleIterator b, final DoubleBinaryOperator zipFunction) {
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final DoubleIterator iterA = a == null ? DoubleIterator.empty() : a;
private final DoubleIterator iterB = b == null ? DoubleIterator.empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext();
}
@Override
public double nextDouble() {
return zipFunction.applyAsDouble(iterA.nextDouble(), iterB.nextDouble());
}
});
}
/**
* 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
* @return
*/
public static DoubleStream zip(final DoubleIterator a, final DoubleIterator b, final DoubleIterator c, final DoubleTernaryOperator zipFunction) {
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final DoubleIterator iterA = a == null ? DoubleIterator.empty() : a;
private final DoubleIterator iterB = b == null ? DoubleIterator.empty() : b;
private final DoubleIterator iterC = c == null ? DoubleIterator.empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public double nextDouble() {
return zipFunction.applyAsDouble(iterA.nextDouble(), iterB.nextDouble(), iterC.nextDouble());
}
});
}
/**
* 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
* @return
*/
public static DoubleStream zip(final DoubleStream a, final DoubleStream b, final DoubleBinaryOperator 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
* @return
*/
public static DoubleStream zip(final DoubleStream a, final DoubleStream b, final DoubleStream c, final DoubleTernaryOperator 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 DoubleStream zip(final Collection c, final DoubleNFunction zipFunction) {
return Stream.zip(c, zipFunction).mapToDouble(com.landawn.abacus.util.function.ToDoubleFunction.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 DoubleStream zip(final double[] a, final double[] b, final double valueForNoneA, final double valueForNoneB,
final DoubleBinaryOperator zipFunction) {
if (N.isNullOrEmpty(a) && N.isNullOrEmpty(b)) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final int aLen = N.len(a), bLen = N.len(b), len = N.max(aLen, bLen);
private int cursor = 0;
private double ret = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public double nextDouble() {
if (cursor >= len) {
throw new NoSuchElementException();
}
ret = zipFunction.applyAsDouble(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 DoubleStream zip(final double[] a, final double[] b, final double[] c, final double valueForNoneA, final double valueForNoneB,
final double valueForNoneC, final DoubleTernaryOperator zipFunction) {
if (N.isNullOrEmpty(a) && N.isNullOrEmpty(b) && N.isNullOrEmpty(c)) {
return empty();
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
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 double ret = 0;
@Override
public boolean hasNext() {
return cursor < len;
}
@Override
public double nextDouble() {
if (cursor >= len) {
throw new NoSuchElementException();
}
ret = zipFunction.applyAsDouble(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 DoubleStream zip(final DoubleIterator a, final DoubleIterator b, final double valueForNoneA, final double valueForNoneB,
final DoubleBinaryOperator zipFunction) {
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final DoubleIterator iterA = a == null ? DoubleIterator.empty() : a;
private final DoubleIterator iterB = b == null ? DoubleIterator.empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext();
}
@Override
public double nextDouble() {
if (iterA.hasNext()) {
return zipFunction.applyAsDouble(iterA.nextDouble(), iterB.hasNext() ? iterB.nextDouble() : valueForNoneB);
} else {
return zipFunction.applyAsDouble(valueForNoneA, iterB.nextDouble());
}
}
});
}
/**
* 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 DoubleStream zip(final DoubleIterator a, final DoubleIterator b, final DoubleIterator c, final double valueForNoneA,
final double valueForNoneB, final double valueForNoneC, final DoubleTernaryOperator zipFunction) {
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final DoubleIterator iterA = a == null ? DoubleIterator.empty() : a;
private final DoubleIterator iterB = b == null ? DoubleIterator.empty() : b;
private final DoubleIterator iterC = c == null ? DoubleIterator.empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext() || iterC.hasNext();
}
@Override
public double nextDouble() {
if (iterA.hasNext()) {
return zipFunction.applyAsDouble(iterA.nextDouble(), iterB.hasNext() ? iterB.nextDouble() : valueForNoneB,
iterC.hasNext() ? iterC.nextDouble() : valueForNoneC);
} else if (iterB.hasNext()) {
return zipFunction.applyAsDouble(valueForNoneA, iterB.nextDouble(), iterC.hasNext() ? iterC.nextDouble() : valueForNoneC);
} else {
return zipFunction.applyAsDouble(valueForNoneA, valueForNoneB, iterC.nextDouble());
}
}
});
}
/**
* 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 DoubleStream zip(final DoubleStream a, final DoubleStream b, final double valueForNoneA, final double valueForNoneB,
final DoubleBinaryOperator 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 DoubleStream zip(final DoubleStream a, final DoubleStream b, final DoubleStream c, final double valueForNoneA, final double valueForNoneB,
final double valueForNoneC, final DoubleTernaryOperator 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 DoubleStream zip(final Collection c, final double[] valuesForNone, final DoubleNFunction zipFunction) {
return Stream.zip(c, valuesForNone, zipFunction).mapToDouble(com.landawn.abacus.util.function.ToDoubleFunction.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 DoubleStream merge(final double[] a, final double[] b, final DoubleBiFunction nextSelector) {
if (N.isNullOrEmpty(a)) {
return of(b);
} else if (N.isNullOrEmpty(b)) {
return of(a);
}
return new IteratorDoubleStream(new DoubleIteratorEx() {
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 double nextDouble() {
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();
}
}
});
}
/**
*
* @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 DoubleStream merge(final double[] a, final double[] b, final double[] c, final DoubleBiFunction nextSelector) {
return merge(merge(a, b, nextSelector).iteratorEx(), DoubleStream.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 DoubleStream merge(final DoubleIterator a, final DoubleIterator b, final DoubleBiFunction nextSelector) {
return new IteratorDoubleStream(new DoubleIteratorEx() {
private final DoubleIterator iterA = a == null ? DoubleIterator.empty() : a;
private final DoubleIterator iterB = b == null ? DoubleIterator.empty() : b;
private double nextA = 0;
private double nextB = 0;
private boolean hasNextA = false;
private boolean hasNextB = false;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext() || hasNextA || hasNextB;
}
@Override
public double nextDouble() {
if (hasNextA) {
if (iterB.hasNext()) {
if (nextSelector.apply(nextA, (nextB = iterB.nextDouble())) == 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.nextDouble()), 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.nextDouble()), (nextB = iterB.nextDouble())) == MergeResult.TAKE_FIRST) {
hasNextB = true;
return nextA;
} else {
hasNextA = true;
return nextB;
}
} else {
return iterA.nextDouble();
}
} else if (iterB.hasNext()) {
return iterB.nextDouble();
} else {
throw new NoSuchElementException();
}
}
});
}
/**
*
* @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 DoubleStream merge(final DoubleIterator a, final DoubleIterator b, final DoubleIterator c, final DoubleBiFunction 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 DoubleStream merge(final DoubleStream a, final DoubleStream b, final DoubleBiFunction 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 DoubleStream merge(final DoubleStream a, final DoubleStream b, final DoubleStream c, final DoubleBiFunction 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 DoubleStream merge(final Collection c, final DoubleBiFunction nextSelector) {
if (N.isNullOrEmpty(c)) {
return empty();
} else if (c.size() == 1) {
return c.iterator().next();
} else if (c.size() == 2) {
final Iterator iter = c.iterator();
return merge(iter.next(), iter.next(), nextSelector);
}
final Iterator iter = c.iterator();
DoubleStream 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 DoubleStream parallelMerge(final Collection c, final DoubleBiFunction 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 DoubleStream parallelMerge(final Collection c, final DoubleBiFunction nextSelector,
final int maxThreadNum) {
N.checkArgument(maxThreadNum > 0, "'maxThreadNum' must not less than 1");
if (maxThreadNum <= 1) {
return merge(c, nextSelector);
} else if (N.isNullOrEmpty(c)) {
return empty();
} else if (c.size() == 1) {
return c.iterator().next();
} else if (c.size() == 2) {
final Iterator iter = c.iterator();
return merge(iter.next(), iter.next(), nextSelector);
} else if (c.size() == 3) {
final Iterator 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, () -> {
DoubleStream a = null;
DoubleStream b = null;
DoubleStream 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 = DoubleStream.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).flatMapToDouble(Supplier::get);
}
public abstract static class DoubleStreamEx extends DoubleStream {
private DoubleStreamEx(boolean sorted, Collection closeHandlers) { //NOSONAR
super(sorted, closeHandlers);
// Factory class.
}
}
}