All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.stream.Stream Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
/*
 * 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.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
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.Queue;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.landawn.abacus.DataSet;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.util.AsyncExecutor;
import com.landawn.abacus.util.ByteIterator;
import com.landawn.abacus.util.CharIterator;
import com.landawn.abacus.util.Charsets;
import com.landawn.abacus.util.ContinuableFuture;
import com.landawn.abacus.util.DoubleIterator;
import com.landawn.abacus.util.Duration;
import com.landawn.abacus.util.FloatIterator;
import com.landawn.abacus.util.Fn;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.IOUtil;
import com.landawn.abacus.util.ImmutableMap;
import com.landawn.abacus.util.Indexed;
import com.landawn.abacus.util.IntIterator;
import com.landawn.abacus.util.IntList;
import com.landawn.abacus.util.Keyed;
import com.landawn.abacus.util.LineIterator;
import com.landawn.abacus.util.ListMultimap;
import com.landawn.abacus.util.LongIterator;
import com.landawn.abacus.util.Matrix;
import com.landawn.abacus.util.Multimap;
import com.landawn.abacus.util.MutableBoolean;
import com.landawn.abacus.util.MutableInt;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.NoCachingNoUpdating;
import com.landawn.abacus.util.NoCachingNoUpdating.DisposableEntry;
import com.landawn.abacus.util.Nth;
import com.landawn.abacus.util.ObjIterator;
import com.landawn.abacus.util.Pair;
import com.landawn.abacus.util.Percentage;
import com.landawn.abacus.util.ShortIterator;
import com.landawn.abacus.util.Try;
import com.landawn.abacus.util.u.Holder;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.BinaryOperator;
import com.landawn.abacus.util.function.BooleanSupplier;
import com.landawn.abacus.util.function.ByteBiFunction;
import com.landawn.abacus.util.function.ByteNFunction;
import com.landawn.abacus.util.function.ByteTriFunction;
import com.landawn.abacus.util.function.CharBiFunction;
import com.landawn.abacus.util.function.CharNFunction;
import com.landawn.abacus.util.function.CharTriFunction;
import com.landawn.abacus.util.function.Consumer;
import com.landawn.abacus.util.function.DoubleBiFunction;
import com.landawn.abacus.util.function.DoubleNFunction;
import com.landawn.abacus.util.function.DoubleTriFunction;
import com.landawn.abacus.util.function.FloatBiFunction;
import com.landawn.abacus.util.function.FloatNFunction;
import com.landawn.abacus.util.function.FloatTriFunction;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntBiFunction;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.IntNFunction;
import com.landawn.abacus.util.function.IntTriFunction;
import com.landawn.abacus.util.function.LongBiFunction;
import com.landawn.abacus.util.function.LongFunction;
import com.landawn.abacus.util.function.LongNFunction;
import com.landawn.abacus.util.function.LongSupplier;
import com.landawn.abacus.util.function.LongTriFunction;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.ShortBiFunction;
import com.landawn.abacus.util.function.ShortNFunction;
import com.landawn.abacus.util.function.ShortTriFunction;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.function.ToByteFunction;
import com.landawn.abacus.util.function.ToCharFunction;
import com.landawn.abacus.util.function.ToDoubleFunction;
import com.landawn.abacus.util.function.ToFloatFunction;
import com.landawn.abacus.util.function.ToIntFunction;
import com.landawn.abacus.util.function.ToLongFunction;
import com.landawn.abacus.util.function.ToShortFunction;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.function.UnaryOperator;
import com.landawn.abacus.util.stream.ObjIteratorEx.QueuedIterator;

/**
 * Note: This class includes codes copied from StreamEx: https://github.com/amaembo/streamex under Apache License, version 2.0.
 * 
* * The Stream will be automatically closed after execution(A terminal method is executed/triggered). * * @param the type of the stream elements * @see IntStream * @see LongStream * @see DoubleStream */ public abstract class Stream extends StreamBase, Consumer, List, Optional, Indexed, ObjIterator, Stream> { static final Random RAND = new SecureRandom(); Stream(final boolean sorted, final Comparator cmp, final Collection closeHandlers) { super(sorted, cmp, closeHandlers); } @SequentialOnly public Stream select(Class targetType) { if (isParallel()) { return (Stream) sequential().filter(Fn.instanceOf(targetType)).parallel(maxThreadNum(), splitor()); } else { return (Stream) filter(Fn.instanceOf(targetType)); } } @ParallelSupported public abstract Stream map(Function mapper); // public abstract Stream biMap(BiFunction mapper); // // /** // * Returns a stream consisting of the results of applying the given function // * to the every two adjacent elements of this stream. // * // *
    //     * 
    //     * Stream.of("a", "b", "c", "d", "e").biMap((i, j) -> i + "-" + j).println();
    //     * // print out: [a-b, c-d, e-null]
    //     * 
    //     * 
// * // * @param mapper // * @param ignoreNotPaired flag to identify if need to ignore the last element when the total length of the stream is odd number. Default value is false // * @return // */ // public abstract Stream biMap(BiFunction mapper, boolean ignoreNotPaired); // // public abstract Stream triMap(TriFunction mapper); // // /** // * Returns a stream consisting of the results of applying the given function // * to the every three adjacent elements of this stream. // * // *
    //     * 
    //     * Stream.of("a", "b", "c", "d", "e").triMap((i, j, k) -> i + "-" + j + "-" + k).println();
    //     * // print out: [a-b-c, d-e-null]
    //     * 
    //     * 
// * // * @param mapper // * @param ignoreNotPaired flag to identify if need to ignore the last one or two elements when the total length of the stream is not multiple of 3. Default value is false // * @return // */ // public abstract Stream triMap(TriFunction mapper, boolean ignoreNotPaired); @ParallelSupported public abstract Stream slidingMap(BiFunction mapper); /** * Slide with windowSize = 2 and the specified increment, then map by the specified mapper. * * @param mapper * @param increment * @return */ @ParallelSupported public abstract Stream slidingMap(BiFunction mapper, int increment); @ParallelSupported public abstract Stream slidingMap(BiFunction mapper, int increment, boolean ignoreNotPaired); @ParallelSupported public abstract Stream slidingMap(TriFunction mapper); /** * Slide with windowSize = 3 and the specified increment, then map by the specified mapper. * * @param mapper * @param increment * @return */ @ParallelSupported public abstract Stream slidingMap(TriFunction mapper, int increment); @ParallelSupported public abstract Stream slidingMap(TriFunction mapper, int increment, boolean ignoreNotPaired); /** * 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. * *
     * 
     * Stream.of("a", "ab", "ac", "b", "c", "cb").rangeMap((a, b) -> b.startsWith(a), (a, b) -> a + "->" + b).toList(); // a->ac, b->b, c->cb
     * 
     * 
* *

* This is a quasi-intermediate * partial reduction operation. * * @param the type of the resulting elements * @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 the new stream * @see #collapse(BiPredicate, BinaryOperator) */ @SequentialOnly public abstract Stream rangeMap(final BiPredicate sameRange, final BiFunction mapper); @ParallelSupported public abstract Stream mapFirst(Function mapperForFirst); @ParallelSupported public abstract Stream mapFirstOrElse(Function mapperForFirst, Function mapperForElse); @ParallelSupported public abstract Stream mapLast(Function mapperForLast); @ParallelSupported public abstract Stream mapLastOrElse(Function mapperForLast, Function mapperForElse); @ParallelSupported public abstract CharStream mapToChar(ToCharFunction mapper); @ParallelSupported public abstract ByteStream mapToByte(ToByteFunction mapper); @ParallelSupported public abstract ShortStream mapToShort(ToShortFunction mapper); @ParallelSupported public abstract IntStream mapToInt(ToIntFunction mapper); @ParallelSupported public abstract LongStream mapToLong(ToLongFunction mapper); @ParallelSupported public abstract FloatStream mapToFloat(ToFloatFunction mapper); @ParallelSupported public abstract DoubleStream mapToDouble(ToDoubleFunction mapper); // public abstract EntryStream mapToEntry(); @ParallelSupported public abstract EntryStream mapToEntry(Function> mapper); @ParallelSupported public abstract EntryStream mapToEntry(Function keyMapper, Function valueMapper); // public abstract Stream mapp(Function> mapper); @ParallelSupported public abstract Stream flatMap(Function> mapper); @ParallelSupported public abstract Stream flattMap(Function> mapper); @ParallelSupported public abstract Stream flatMapp(Function mapper); @ParallelSupported public abstract CharStream flatMapToChar(Function mapper); @ParallelSupported public abstract CharStream flattMapToChar(Function mapper); @ParallelSupported public abstract ByteStream flatMapToByte(Function mapper); @ParallelSupported public abstract ByteStream flattMapToByte(Function mapper); @ParallelSupported public abstract ShortStream flatMapToShort(Function mapper); @ParallelSupported public abstract ShortStream flattMapToShort(Function mapper); @ParallelSupported public abstract IntStream flatMapToInt(Function mapper); @ParallelSupported public abstract IntStream flattMapToInt(Function mapper); @ParallelSupported public abstract LongStream flatMapToLong(Function mapper); @ParallelSupported public abstract LongStream flattMapToLong(Function mapper); @ParallelSupported public abstract FloatStream flatMapToFloat(Function mapper); @ParallelSupported public abstract FloatStream flattMapToFloat(Function mapper); @ParallelSupported public abstract DoubleStream flatMapToDouble(Function mapper); @ParallelSupported public abstract DoubleStream flattMapToDouble(Function mapper); @ParallelSupported public abstract EntryStream flatMapToEntry(Function>> mapper); @ParallelSupported public abstract EntryStream flattMapToEntry(Function> mapper); @ParallelSupported public abstract EntryStream flatMappToEntry(Function> mapper); @ParallelSupported public abstract Stream>> groupBy(final Function keyMapper); @ParallelSupported public abstract Stream>> groupBy(final Function keyMapper, final Supplier>> mapFactory); /** * * @param keyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract Stream>> groupBy(Function keyMapper, Function valueMapper); /** * * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract Stream>> groupBy(Function keyMapper, Function valueMapper, Supplier>> mapFactory); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Collector downstream); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Collector downstream, final Supplier> mapFactory); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Function valueMapper, final Collector downstream); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Function valueMapper, final Collector downstream, final Supplier> mapFactory); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Function valueMapper, BinaryOperator mergeFunction); @ParallelSupported public abstract Stream> groupBy(final Function keyMapper, final Function valueMapper, final BinaryOperator mergeFunction, final Supplier> mapFactory); // @ParallelSupported // public abstract Stream>> flatGroupBy(final Function> flatKeyMapper); // // @ParallelSupported // public abstract Stream>> flatGroupBy(final Function> flatKeyMapper, // final Supplier>> mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @return // * @see Collectors#toMultimap(Function, Function) // */ // @ParallelSupported // public abstract Stream>> flatGroupBy(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#toMultimap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract Stream>> flatGroupBy(Function> flatKeyMapper, // BiFunction valueMapper, Supplier>> mapFactory); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final Collector downstream); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final Collector downstream, final Supplier> mapFactory); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream, // final Supplier> mapFactory); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, BinaryOperator mergeFunction); // // @ParallelSupported // public abstract Stream> flatGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final BinaryOperator mergeFunction, // final Supplier> mapFactory); // // @ParallelSupported // public abstract Stream>> flattGroupBy(final Function> flatKeyMapper); // // @ParallelSupported // public abstract Stream>> flattGroupBy(final Function> flatKeyMapper, // final Supplier>> mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @return // * @see Collectors#toMultimap(Function, Function) // */ // @ParallelSupported // public abstract Stream>> flattGroupBy(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#toMultimap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract Stream>> flattGroupBy(Function> flatKeyMapper, // BiFunction valueMapper, Supplier>> mapFactory); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final Collector downstream); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final Collector downstream, final Supplier> mapFactory); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream, // final Supplier> mapFactory); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, BinaryOperator mergeFunction); // // @ParallelSupported // public abstract Stream> flattGroupBy(final Function> flatKeyMapper, // final BiFunction valueMapper, final BinaryOperator mergeFunction, // final Supplier> mapFactory); /** * * @param predicate * @return * @see Collectors#partitioningBy(Predicate) */ @ParallelSupported public abstract Stream>> partitionBy(final Predicate predicate); /** * * @param predicate * @param downstream * @return * @see Collectors#partitioningBy(Predicate, Collector) */ @ParallelSupported public abstract Stream> partitionBy(final Predicate predicate, final Collector downstream); @ParallelSupported public Stream> countBy(final Function keyMapper) { return groupBy(keyMapper, Collectors.countingInt()); } @ParallelSupported public abstract EntryStream> groupByToEntry(final Function keyMapper); @ParallelSupported public abstract EntryStream> groupByToEntry(final Function keyMapper, final Supplier>> mapFactory); /** * * @param keyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract EntryStream> groupByToEntry(Function keyMapper, Function valueMapper); /** * * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract EntryStream> groupByToEntry(Function keyMapper, Function valueMapper, Supplier>> mapFactory); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Collector downstream); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Collector downstream, final Supplier> mapFactory); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Function valueMapper, final Collector downstream); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Function valueMapper, final Collector downstream, final Supplier> mapFactory); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Function valueMapper, BinaryOperator mergeFunction); @ParallelSupported public abstract EntryStream groupByToEntry(final Function keyMapper, final Function valueMapper, final BinaryOperator mergeFunction, final Supplier> mapFactory); /** * * @param predicate * @return * @see Collectors#partitioningBy(Predicate) */ @ParallelSupported public abstract EntryStream> partitionByToEntry(final Predicate predicate); /** * * @param predicate * @param downstream * @return * @see Collectors#partitioningBy(Predicate, Collector) */ @ParallelSupported public abstract EntryStream partitionByToEntry(final Predicate predicate, final Collector downstream); @ParallelSupported public EntryStream countByToEntry(final Function keyMapper) { return groupByToEntry(keyMapper, Collectors.countingInt()); } @SequentialOnly public abstract Stream> collapse(final BiPredicate collapsible); @SequentialOnly public abstract > Stream collapse(final BiPredicate collapsible, Supplier supplier); /** * Merge series of adjacent elements which satisfy the given predicate using * the merger function and return a new stream. * *

Example: *

     * 
     * Stream.of(new Integer[0]).collapse((a, b) -> a < b, (a, b) -> a + b) => []
     * Stream.of(1).collapse((a, b) -> a < b, (a, b) -> a + b) => [1]
     * Stream.of(1, 2).collapse((a, b) -> a < b, (a, b) -> a + b) => [3]
     * Stream.of(1, 2, 3).collapse((a, b) -> a < b, (a, b) -> a + b) => [6]
     * Stream.of(1, 2, 3, 3, 2, 1).collapse((a, b) -> a < b, (a, b) -> a + b) => [6, 3, 2, 1]
     * 
     * 
* *
* This method only run sequentially, even in parallel stream. * * @param collapsible * @param mergeFunction * @return */ @SequentialOnly public abstract Stream collapse(final BiPredicate collapsible, final BiFunction mergeFunction); @SequentialOnly public abstract Stream collapse(final BiPredicate collapsible, final R init, final BiFunction op); @SequentialOnly public abstract Stream collapse(final BiPredicate collapsible, final Supplier supplier, final BiConsumer accumulator); /** * Merge series of adjacent elements which satisfy the given predicate using * the merger function and return a new stream. * *

Example: *

     * 
     * Stream.of(new Integer[0]).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => []
     * Stream.of(1).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [1]
     * Stream.of(1, 2).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [3]
     * Stream.of(1, 2, 3).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [6]
     * Stream.of(1, 2, 3, 3, 2, 1).collapse((a, b) -> a < b, Collectors.summingInt(Fn.unboxI())) => [6, 3, 2, 1]
     * 
     * 
* *
* This method only run sequentially, even in parallel stream. * * @param collapsible * @param collector * @return */ @SequentialOnly public abstract Stream collapse(final BiPredicate collapsible, final Collector collector); /** * 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: *

     * 
     * Stream.of(new Integer[0]).scan((a, b) -> a + b) => []
     * Stream.of(1).scan((a, b) -> a + b) => [1]
     * Stream.of(1, 2).scan((a, b) -> a + b) => [1, 3]
     * Stream.of(1, 2, 3).scan((a, b) -> a + b) => [1, 3, 6]
     * Stream.of(1, 2, 3, 3, 2, 1).scan((a, b) -> a + b) => [1, 3, 6, 9, 11, 12]
     * 
     * 
* *
* This method only run sequentially, even in parallel stream. * * @param accumulator the accumulation function * @return the new stream which has the extract same size as this stream. */ @SequentialOnly public abstract Stream scan(final BiFunction 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: *

     * 
     * Stream.of(new Integer[0]).scan(10, (a, b) -> a + b) => []
     * Stream.of(1).scan(10, (a, b) -> a + b) => [11]
     * Stream.of(1, 2).scan(10, (a, b) -> a + b) => [11, 13]
     * Stream.of(1, 2, 3).scan(10, (a, b) -> a + b) => [11, 13, 16]
     * Stream.of(1, 2, 3, 3, 2, 1).scan(10, (a, b) -> a + b) => [11, 13, 16, 19, 21, 22]
     * 
     * 
* *
* This method only run 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 the new stream which has the extract same size as this stream. */ @SequentialOnly public abstract Stream scan(final R init, final BiFunction accumulator); /** * * @param init * @param accumulator * @param initIncluded * @return */ @SequentialOnly public abstract Stream scan(final R init, final BiFunction accumulator, final boolean initIncluded); /** * Returns Stream of Stream with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). * *
* This method only run sequentially, even in parallel stream. * * @param size * @return */ @SequentialOnly public abstract Stream> splitToSet(int size); /** * Returns Stream of Stream with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). * *
* This method only run sequentially, even in parallel stream. * * @param size * @param collectionSupplier * @return */ @SequentialOnly public abstract > Stream split(int size, IntFunction collectionSupplier); @SequentialOnly public abstract Stream split(int size, Collector collector); @SequentialOnly public abstract Stream> splitToSet(Predicate predicate); @SequentialOnly public abstract > Stream split(Predicate predicate, Supplier collectionSupplier); @SequentialOnly public abstract Stream split(Predicate predicate, Collector collector); @SequentialOnly public abstract Stream splitAt(int where, Collector collector); @SequentialOnly public abstract Stream splitBy(Predicate where, Collector collector); @SequentialOnly public abstract > Stream sliding(int windowSize, IntFunction collectionSupplier); @SequentialOnly public abstract > Stream sliding(int windowSize, int increment, IntFunction collectionSupplier); @SequentialOnly public abstract Stream sliding(int windowSize, Collector collector); @SequentialOnly public abstract Stream sliding(int windowSize, int increment, Collector collector); /** * Split this stream by the specified duration. * * @param duration * @return * @see Fn#window(Duration, LongSupplier) */ @SequentialOnly public abstract Stream> window(Duration duration); /** * * @param duration * @param startTime * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> window(Duration duration, LongSupplier startTime); /** * * @param duration * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> windowToList(Duration duration); /** * * @param duration * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> windowToSet(Duration duration); /** * * @param duration * @param collectionSupplier * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(Duration duration, Supplier collectionSupplier); /** * * @param duration * @param startTime * @param collectionSupplier * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(Duration duration, LongSupplier startTime, Supplier collectionSupplier); /** * * @param duration * @param collector * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(Duration duration, Collector collector); /** * * @param duration * @param startTime * @param collector * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(Duration duration, LongSupplier startTime, Collector collector); /** * * @param duration * @param incrementInMillis * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> window(Duration duration, long incrementInMillis); /** * * @param duration * @param incrementInMillis * @param startTime * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> window(Duration duration, long incrementInMillis, LongSupplier startTime); /** * * @param duration * @param incrementInMillis * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> windowToList(Duration duration, long incrementInMillis); /** * * @param duration * @param incrementInMillis * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> windowToSet(Duration duration, long incrementInMillis); /** * * @param duration * @param incrementInMillis * @param collectionSupplier * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(Duration duration, long incrementInMillis, Supplier collectionSupplier); /** * * @param duration * @param incrementInMillis * @param startTime * @param collectionSupplier * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(Duration duration, long incrementInMillis, LongSupplier startTime, Supplier collectionSupplier); /** * * @param duration * @param incrementInMillis * @param collector * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(Duration duration, long incrementInMillis, Collector collector); /** * * @param duration * @param incrementInMillis * @param startTime * @param collector * @return * @see #window(Duration) * @see Fn#window(Duration, LongSupplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(Duration duration, long incrementInMillis, LongSupplier startTime, Collector collector); /** * * @param maxWindowSize * @param maxDuration * @return * @see #window(int, Duration, LongSupplier, Supplier) * @see Fn#window(int, Duration, LongSupplier, Supplier) */ @SequentialOnly public abstract Stream> window(int maxWindowSize, Duration maxDuration); /** * * @param maxWindowSize * @param maxDuration * @param startTime * @return * @see #window(int, Duration, LongSupplier, Supplier) * @see Fn#window(int, Duration, LongSupplier, Supplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream> window(int maxWindowSize, Duration maxDuration, LongSupplier startTime); /** * * @param maxWindowSize * @param maxDuration * @param collectionSupplier * @return * @see #window(int, Duration, LongSupplier, Supplier) * @see Fn#window(int, Duration, LongSupplier, Supplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(int maxWindowSize, Duration maxDuration, Supplier collectionSupplier); /** * Split this stream at where {@code maxWindowSize} or {@code maxDuration} reaches first. * * @param maxWindowSize * @param maxDuration * @param startTime * @param collectionSupplier * @return * @see #window(int, Duration, LongSupplier, Supplier) * @see Fn#window(int, Duration, LongSupplier, Supplier) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract > Stream window(int maxWindowSize, Duration maxDuration, LongSupplier startTime, Supplier collectionSupplier); /** * * @param maxWindowSize * @param maxDuration * @param collector * @return * @see #window(int, Duration, LongSupplier, Collector) * @see Fn#window(int, Duration, LongSupplier, Collector) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(int maxWindowSize, Duration maxDuration, Collector collector); /** * Split this stream at where {@code maxWindowSize} or {@code maxDuration} reaches first. * * @param maxWindowSize * @param maxDuration * @param startTime * @param collector * @return * @see #window(Duration, long, LongSupplier, Collector) * @see Fn#window(int, Duration, LongSupplier, Collector) * @see #sliding(int, int, Collector) */ @SequentialOnly public abstract Stream window(int maxWindowSize, Duration maxDuration, LongSupplier startTime, Collector collector); /** * Stream.of(1).intersperse(9) --> [1] * Stream.of(1, 2, 3).intersperse(9) --> [1, 9, 2, 9, 3] * *
* This method only run sequentially, even in parallel stream. * * @param delimiter * @return */ @SequentialOnly public abstract Stream intersperse(T delimiter); /** * Distinct and filter by occurrences. * * @param occurrencesFilter * @return */ @ParallelSupported public Stream distinct(final Predicate occurrencesFilter) { final Supplier> supplier = isParallel() ? Suppliers. ofConcurrentHashMap() : Suppliers. ofLinkedHashMap(); return groupBy(Fn. identity(), Collectors.counting(), supplier).filter(Fn. testByValue(occurrencesFilter)).map(Fn. key()); } /** * Distinct by the value mapped from keyMapper * * @param keyMapper don't change value of the input parameter. * @return */ @ParallelSupported public abstract Stream distinctBy(Function keyMapper); /** * Distinct and filter by occurrences. * * @param keyMapper * @param occurrencesFilter * @return */ public Stream distinctBy(final Function keyMapper, final Predicate occurrencesFilter) { final Supplier, Long>> supplier = isParallel() ? Suppliers., Long> ofConcurrentHashMap() : Suppliers., Long> ofLinkedHashMap(); return groupBy(Fn. keyed(keyMapper), Collectors.counting(), supplier).filter(Fn., Long> testByValue(occurrencesFilter)) .map(Fn. kk()); } /** * *
* This method only run sequentially, even in parallel stream. * * @param n * @return */ @SequentialOnly public abstract Stream top(int n); /** *
* This method only run sequentially, even in parallel stream. * * @param n * @param comparator * @return */ @SequentialOnly public abstract Stream top(int n, Comparator comparator); @ParallelSupported public abstract Stream sorted(Comparator comparator); @SuppressWarnings("rawtypes") @ParallelSupported public abstract Stream sortedBy(Function keyMapper); @ParallelSupported public abstract Stream sortedByInt(ToIntFunction keyMapper); @ParallelSupported public abstract Stream sortedByLong(ToLongFunction keyMapper); @ParallelSupported public abstract Stream sortedByDouble(ToDoubleFunction keyMapper); @ParallelSupported public abstract void forEach(Try.Consumer action) throws E; @ParallelSupported public abstract void forEach(Try.Consumer action, Try.Runnable onComplete) throws E, E2; public abstract void forEach(final Try.Function, E> flatMapper, final Try.BiConsumer action) throws E, E2; public abstract void forEach( final Try.Function, E> flatMapper, final Try.Function, E2> flatMapper2, final Try.TriConsumer action) throws E, E2, E3; @ParallelSupported public abstract void forEachPair(final Try.BiConsumer action) throws E; /** * Slide with windowSize = 2 and the specified increment, then consume by the specified mapper. * * @param mapper * @param increment * @return */ @ParallelSupported public abstract void forEachPair(final Try.BiConsumer action, final int increment) throws E; @ParallelSupported public abstract void forEachTriple(final Try.TriConsumer action) throws E; /** * Slide with windowSize = 3 and the specified increment, then consume by the specified mapper. * * @param mapper * @param increment * @return */ @ParallelSupported public abstract void forEachTriple(final Try.TriConsumer action, final int increment) throws E; @ParallelSupported public abstract boolean anyMatch(Try.Predicate predicate) throws E; @ParallelSupported public abstract boolean allMatch(Try.Predicate predicate) throws E; @ParallelSupported public abstract boolean noneMatch(Try.Predicate predicate) throws E; @ParallelSupported public abstract boolean nMatch(long atLeast, long atMost, Try.Predicate predicate) throws E; @ParallelSupported public abstract Optional findFirst(Try.Predicate predicate) throws E; @ParallelSupported public abstract Optional findLast(Try.Predicate predicate) throws E; @SequentialOnly public abstract Optional findFirstOrLast(Try.Predicate predicateForFirst, Try.Predicate predicateForLast) throws E, E2; /** *
* This method only run sequentially, even in parallel stream. * * @param init * @param predicateForFirst * @param predicateForLast * @return */ @SequentialOnly public abstract Optional findFirstOrLast(final U init, final Try.BiPredicate predicateForFirst, final Try.BiPredicate predicateForLast) throws E, E2; /** *
* This method only run sequentially, even in parallel stream. * * @param preFunc * @param predicateForFirst * @param predicateForLast * @return */ @SequentialOnly public abstract Optional findFirstOrLast(final Function preFunc, final Try.BiPredicate predicateForFirst, final Try.BiPredicate predicateForLast) throws E, E2; @ParallelSupported public abstract Optional findAny(Try.Predicate predicate) throws E; @SequentialOnly public abstract boolean containsAll(T... a); @SequentialOnly public abstract boolean containsAll(Collection c); @SequentialOnly public abstract A[] toArray(IntFunction generator); /** * * @param keyMapper * @param valueMapper * @return * @see Collectors#toMap(Function, Function) */ @ParallelSupported public ImmutableMap toImmutableMap(Function keyMapper, Function valueMapper) { return ImmutableMap.of(toMap(keyMapper, valueMapper)); } /** * * @param keyMapper * @param valueMapper * @param mergeFunction * @return * @see Collectors#toMap(Function, Function) */ @ParallelSupported public ImmutableMap toImmutableMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) { return ImmutableMap.of(toMap(keyMapper, valueMapper, mergeFunction)); } /** * * @param keyMapper * @param valueMapper * @return * @see Collectors#toMap(Function, Function) */ @ParallelSupported public abstract Map toMap(Function keyMapper, Function valueMapper); /** * * @param keyMapper * @param valueMapper * @param mergeFunction * @return * @see Collectors#toMap(Function, Function, BinaryOperator) */ @ParallelSupported public abstract Map toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction); /** * * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMap(Function, Function, Supplier) */ @ParallelSupported public abstract > M toMap(Function keyMapper, Function valueMapper, Supplier mapFactory); /** * * @param keyMapper * @param valueMapper * @param mergeFunction * @param mapFactory * @return * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) */ @ParallelSupported public abstract > M toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier mapFactory); /** * * @param keyMapper * @param downstream * @return * @see Collectors#groupingBy(Function, Collector) */ @ParallelSupported public abstract Map toMap(final Function keyMapper, final Collector downstream); /** * * @param keyMapper * @param downstream * @param mapFactory * @return * @see Collectors#groupingBy(Function, Collector, Supplier) */ @ParallelSupported public abstract > M toMap(final Function keyMapper, final Collector downstream, final Supplier mapFactory); /** * * @param keyMapper * @param valueMapper * @param downstream * @return * @see Collectors#groupingBy(Function, Collector) */ @ParallelSupported public abstract Map toMap(final Function keyMapper, final Function valueMapper, final Collector downstream); /** * * @param keyMapper * @param valueMapper * @param downstream * @param mapFactory * @return * @see Collectors#groupingBy(Function, Collector, Supplier) */ @ParallelSupported public abstract > M toMap(final Function keyMapper, final Function valueMapper, final Collector downstream, final Supplier mapFactory); // /** // * // * @param flatKeyMapper // * @param valueMapper // * @return // * @see Collectors#toMap(Function, Function) // */ // @ParallelSupported // public abstract Map flatToMap(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mergeFunction // * @return // * @see Collectors#toMap(Function, Function, BinaryOperator) // */ // @ParallelSupported // public abstract Map flatToMap(Function> flatKeyMapper, // BiFunction valueMapper, BinaryOperator mergeFunction); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#toMap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract > M flatToMap(Function> flatKeyMapper, // BiFunction valueMapper, Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mergeFunction // * @param mapFactory // * @return // * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) // */ // @ParallelSupported // public abstract > M flatToMap(Function> flatKeyMapper, // BiFunction valueMapper, BinaryOperator mergeFunction, Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param downstream // * @return // * @see Collectors#groupingBy(Function, Collector) // */ // @ParallelSupported // public abstract Map flatToMap(final Function> flatKeyMapper, // final Collector downstream); // // /** // * // * @param flatKeyMapper // * @param downstream // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Collector, Supplier) // */ // @ParallelSupported // public abstract > M flatToMap(final Function> flatKeyMapper, // final Collector downstream, final Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param downstream // * @return // * @see Collectors#groupingBy(Function, Collector) // */ // @ParallelSupported // public abstract Map flatToMap(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param downstream // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Collector, Supplier) // */ // @ParallelSupported // public abstract > M flatToMap(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream, // final Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @return // * @see Collectors#flattToMap(Function, Function) // */ // @ParallelSupported // public abstract Map flattToMap(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mergeFunction // * @return // * @see Collectors#flattToMap(Function, Function, BinaryOperator) // */ // @ParallelSupported // public abstract Map flattToMap(Function> flatKeyMapper, // BiFunction valueMapper, BinaryOperator mergeFunction); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#flattToMap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract > M flattToMap(Function> flatKeyMapper, // BiFunction valueMapper, Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mergeFunction // * @param mapFactory // * @return // * @see Collectors#flattToMap(Function, Function, BinaryOperator, Supplier) // */ // @ParallelSupported // public abstract > M flattToMap(Function> flatKeyMapper, // BiFunction valueMapper, BinaryOperator mergeFunction, Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param downstream // * @return // * @see Collectors#groupingBy(Function, Collector) // */ // @ParallelSupported // public abstract Map flattToMap(final Function> flatKeyMapper, // final Collector downstream); // // /** // * // * @param flatKeyMapper // * @param downstream // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Collector, Supplier) // */ // @ParallelSupported // public abstract > M flattToMap(final Function> flatKeyMapper, // final Collector downstream, final Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param downstream // * @return // * @see Collectors#groupingBy(Function, Collector) // */ // @ParallelSupported // public abstract Map flattToMap(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param downstream // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Collector, Supplier) // */ // @ParallelSupported // public abstract > M flattToMap(final Function> flatKeyMapper, // final BiFunction valueMapper, final Collector downstream, // final Supplier mapFactory); /** * * @param keyMapper * @return * @see Collectors#groupingBy(Function) */ @ParallelSupported public abstract Map> groupTo(Function keyMapper); /** * * @param keyMapper * @param mapFactory * @return * @see Collectors#groupingBy(Function, Supplier) */ @ParallelSupported public abstract >> M groupTo(final Function keyMapper, final Supplier mapFactory); @ParallelSupported public abstract Map> groupTo(Function keyMapper, Function valueMapper); /** * * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract >> M groupTo(Function keyMapper, Function valueMapper, Supplier mapFactory); // /** // * // * @param flatKeyMapper // * @return // * @see Collectors#groupingBy(Function) // */ // @ParallelSupported // public abstract Map> flatGroupTo(Function> flatKeyMapper); // // /** // * // * @param flatKeyMapper // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Supplier) // */ // @ParallelSupported // public abstract >> M flatGroupTo(final Function> flatKeyMapper, // final Supplier mapFactory); // // @ParallelSupported // public abstract Map> flatGroupTo(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#toMultimap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract >> M flatGroupTo(Function> flatKeyMapper, // BiFunction valueMapper, Supplier mapFactory); // // /** // * // * @param flatKeyMapper // * @return // * @see Collectors#groupingBy(Function) // */ // @ParallelSupported // public abstract Map> flattGroupTo(Function> flatKeyMapper); // // /** // * // * @param flatKeyMapper // * @param mapFactory // * @return // * @see Collectors#groupingBy(Function, Supplier) // */ // @ParallelSupported // public abstract >> M flattGroupTo(final Function> flatKeyMapper, // final Supplier mapFactory); // // @ParallelSupported // public abstract Map> flattGroupTo(Function> flatKeyMapper, // BiFunction valueMapper); // // /** // * // * @param flatKeyMapper // * @param valueMapper // * @param mapFactory // * @return // * @see Collectors#toMultimap(Function, Function, Supplier) // */ // @ParallelSupported // public abstract >> M flattGroupTo(Function> flatKeyMapper, // BiFunction valueMapper, Supplier mapFactory); /** * * @param predicate * @return * @see Collectors#partitioningBy(Predicate) */ @ParallelSupported public abstract Map> partitionTo(final Predicate predicate); /** * * @param predicate * @param downstream * @return * @see Collectors#partitioningBy(Predicate, Collector) */ @ParallelSupported public abstract Map partitionTo(final Predicate predicate, final Collector downstream); /** * * @param keyMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap toMultimap(Function keyMapper); /** * * @param keyMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M toMultimap(Function keyMapper, Supplier mapFactory); /** * * @param keyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap toMultimap(Function keyMapper, Function valueMapper); /** * * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M toMultimap(Function keyMapper, Function valueMapper, Supplier mapFactory); /** * * @param flatKeyMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap flatToMultimap(Function> flatKeyMapper); /** * * @param flatKeyMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M flatToMultimap(Function> flatKeyMapper, Supplier mapFactory); /** * * @param flatKeyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap flatToMultimap(Function> flatKeyMapper, BiFunction valueMapper); /** * * @param flatKeyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M flatToMultimap( Function> flatKeyMapper, BiFunction valueMapper, Supplier mapFactory); /** * * @param flatKeyMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap flattToMultimap(Function> flatKeyMapper); /** * * @param flatKeyMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M flattToMultimap( Function> flatKeyMapper, Supplier mapFactory); /** * * @param flatKeyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @ParallelSupported public abstract ListMultimap flattToMultimap(Function> flatKeyMapper, BiFunction valueMapper); /** * * @param flatKeyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @ParallelSupported public abstract , M extends Multimap> M flattToMultimap( Function> flatKeyMapper, BiFunction valueMapper, Supplier mapFactory); @SequentialOnly public abstract Matrix toMatrix(Class type); /** * * @return */ @SequentialOnly public abstract DataSet toDataSet(); /** * @param isFirstTitle * @return */ @SequentialOnly public abstract DataSet toDataSet(boolean isFirstTitle); /** * * @param columnNames it can be null or empty if this is Map or entity stream. * @return */ @SequentialOnly public abstract DataSet toDataSet(final List columnNames); @ParallelSupported public abstract T reduce(T identity, BinaryOperator accumulator); @ParallelSupported public abstract Optional reduce(BinaryOperator accumulator); @ParallelSupported public abstract R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner); @ParallelSupported public abstract R collect(Supplier supplier, BiConsumer accumulator); @ParallelSupported public abstract R collect(Collector collector); public abstract R collect(java.util.stream.Collector collector); @ParallelSupported public abstract RR collectAndThen(Collector downstream, Function func); @ParallelSupported public abstract RR collectAndThen(java.util.stream.Collector downstream, java.util.function.Function func); @SequentialOnly public abstract R toListAndThen(Function, R> func); @SequentialOnly public abstract R toSetAndThen(Function, R> func); /** * A queue with size up to n will be maintained to filter out the last n elements. * It may cause out of memory error if n is big enough. * *
* * All the elements will be loaded to get the last {@code n} elements and the Stream will be closed after that, if a terminal operation is triggered. * * @param n * @return */ @SequentialOnly public abstract Stream last(int n); /** * A queue with size up to n will be maintained to filter out the last n elements. * It may cause out of memory error if n is big enough. * *
* This method only run sequentially, even in parallel stream. * * @param n * @return */ @SequentialOnly public abstract Stream skipLast(int n); @ParallelSupported public abstract Optional min(Comparator comparator); @SuppressWarnings("rawtypes") @ParallelSupported public Optional minBy(final Function keyMapper) { final Comparator comparator = Fn.comparingBy(keyMapper); return min(comparator); } @ParallelSupported public abstract Optional max(Comparator comparator); @SuppressWarnings("rawtypes") @ParallelSupported public Optional maxBy(final Function keyMapper) { final Comparator comparator = Fn.comparingBy(keyMapper); return max(comparator); } /** * * @param k * @param comparator * @return Optional.empty() if there is no element or count less than k, otherwise the kth largest element. */ @ParallelSupported public abstract Optional kthLargest(int k, Comparator comparator); @ParallelSupported public abstract int sumInt(ToIntFunction mapper); @ParallelSupported public abstract long sumLong(ToLongFunction mapper); @ParallelSupported public abstract double sumDouble(ToDoubleFunction mapper); @ParallelSupported public abstract OptionalDouble averageInt(ToIntFunction mapper); @ParallelSupported public abstract OptionalDouble averageLong(ToLongFunction mapper); @ParallelSupported public abstract OptionalDouble averageDouble(ToDoubleFunction mapper); @SequentialOnly public abstract Optional> percentiles(Comparator comparator); /** *
     * 
     * Stream.of(1, 2, 3).combinations().forEach(Fn.println());
     * // output
     * []
     * [1]
     * [2]
     * [3]
     * [1, 2]
     * [1, 3]
     * [2, 3]
     * [1, 2, 3]
     * 
     * 
* * @return */ @SequentialOnly public abstract Stream> combinations(); /** *
     * 
     * Stream.of(1, 2, 3).combinations(2).forEach(Fn.println());
     * // output
     * [1, 2]
     * [1, 3]
     * [2, 3]
     * 
     * 
* * @param len * @return */ @SequentialOnly public abstract Stream> combinations(int len); /** * It's same as {@code N.cartesianProduct(N.repeat(toList(), len))} if {@code repeat} is {@code true}. *
     * 
     * Stream.of(1, 2, 3).combinations(2, true).forEach(Fn.println());
     * // output
     * [1, 1]
     * [1, 2]
     * [1, 3]
     * [2, 1]
     * [2, 2]
     * [2, 3]
     * [3, 1]
     * [3, 2]
     * [3, 3]
     * 
     * 
* * @param len * @param repeat * @return */ @SequentialOnly public abstract Stream> combinations(int len, boolean repeat); /** *
     * 
     * Stream.of(1, 2, 3).permutations().forEach(Fn.println());
     * // output
     * [1, 2, 3]
     * [1, 3, 2]
     * [3, 1, 2]
     * [3, 2, 1]
     * [2, 3, 1]
     * [2, 1, 3]
     * 
     * 
* * @return */ @SequentialOnly public abstract Stream> permutations(); /** *
     * 
     * Stream.of(1, 2, 3).orderedPermutations().forEach(Fn.println());
     * // output
     * [1, 2, 3]
     * [1, 3, 2]
     * [2, 1, 3]
     * [2, 3, 1]
     * [3, 1, 2]
     * [3, 2, 1]
     * 
     * 
* * @return */ @SequentialOnly public abstract Stream> orderedPermutations(); @SequentialOnly public abstract Stream> orderedPermutations(Comparator comparator); @SequentialOnly @SafeVarargs public final Stream> cartesianProduct(Collection... cs) { return cartesianProduct(Arrays.asList(cs)); } @SequentialOnly public abstract Stream> cartesianProduct(Collection> cs); /** * * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param b * @param leftKeyMapper * @param rightKeyMapper * @return * @see
Stream> innerJoin(Collection b, BiPredicate predicate); /** * * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param b * @param leftKeyMapper * @param rightKeyMapper * @return * @see Stream> fullJoin(Collection b, BiPredicate predicate); /** * * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param b * @param leftKeyMapper * @param rightKeyMapper * @return * @see Stream> leftJoin(Collection b, BiPredicate predicate); /** * * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param b * @param leftKeyMapper * @param rightKeyMapper * @return * @see Stream> rightJoin(Collection b, BiPredicate predicate); @SequentialOnly public abstract boolean hasDuplicates(); @ParallelSupported public abstract Stream skipNull(); @ParallelSupported public abstract Stream peekFirst(Consumer action); @ParallelSupported public abstract Stream peekLast(Consumer action); /** * Intersect with the specified Collection by the values mapped by mapper. * * @param mapper * @param c * @return * @see IntList#intersection(IntList) */ @ParallelSupported public abstract Stream intersection(Function mapper, Collection c); /** * Except with the specified Collection by the values mapped by mapper. * * @param mapper * @param c * @return * @see IntList#difference(IntList) */ @ParallelSupported public abstract Stream difference(Function mapper, Collection c); @SafeVarargs @SequentialOnly public final Stream append(T... a) { return append(Arrays.asList(a)); } @SequentialOnly public abstract Stream append(Collection c); @SequentialOnly public abstract Stream appendAlll(Collection> cs); @SafeVarargs @SequentialOnly public final Stream prepend(T... a) { return prepend(Arrays.asList(a)); } @SequentialOnly public abstract Stream prepend(Collection c); @SequentialOnly public abstract Stream prependAlll(Collection> cs); @SafeVarargs @SequentialOnly public final Stream appendIfEmpty(T... a) { return appendIfEmpty(Arrays.asList(a)); } @SequentialOnly public abstract Stream appendIfEmpty(Collection c); // /** // * Returns a reusable stream which can be repeatedly used. // * // *
// * All elements will be loaded to memory. // * // * @param generator // * @return // */ // @SequentialOnly // public abstract Stream cached(IntFunction generator); /** * The Stream will be closed finally, no matter it's empty or not. * * @param func * @return */ @Beta public abstract Optional applyIfNotEmpty(Try.Function, R, E> func) throws E; /** * The Stream will be closed finally, no matter it's empty or not. * * @param action * */ @Beta public abstract void acceptIfNotEmpty(Try.Consumer, E> action) throws E; /** * Returns a new Stream with elements from a temporary queue which is filled by reading the elements from this Stream asynchronously. * Default queue size is 64. * * @return */ @SequentialOnly public abstract Stream queued(); /** * Returns a new Stream with elements from a temporary queue which is filled by reading the elements from this Stream asynchronously. * * @param queueSize * @return */ @SequentialOnly public abstract Stream queued(int queueSize); /** * * @param b * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ @SequentialOnly public abstract Stream merge(final Stream b, final BiFunction nextSelector); @ParallelSupported public abstract Stream zipWith(final Stream b, final BiFunction zipFunction); @ParallelSupported public abstract Stream zipWith(final Stream b, final Stream c, final TriFunction zipFunction); @ParallelSupported public abstract Stream zipWith(final Stream b, final T valueForNoneA, final T2 valueForNoneB, final BiFunction zipFunction); @ParallelSupported public abstract Stream zipWith(final Stream b, final Stream c, final T valueForNoneA, final T2 valueForNoneB, final T3 valueForNoneC, final TriFunction zipFunction); @SequentialOnly public abstract long persist(File file, Try.Function toLine) throws IOException; @SequentialOnly public abstract long persist(OutputStream os, Try.Function toLine) throws IOException; @SequentialOnly public abstract long persist(Writer writer, Try.Function toLine) throws IOException; @SequentialOnly public abstract long persist(final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws SQLException; @SequentialOnly public abstract long persist(final PreparedStatement stmt, final int batchSize, final int batchInterval, final Try.BiConsumer stmtSetter) throws SQLException; /** * Remember to close this Stream after the iteration is done, if required. * * @return */ @SequentialOnly public abstract java.util.stream.Stream toJdkStream(); @SequentialOnly @Override public ObjIterator iterator() { return iteratorEx(); } abstract ObjIteratorEx iteratorEx(); /** * * @param action a terminal operation should be called. * @return */ public ContinuableFuture asyncRun(final Try.Consumer, E> action) { checkArgNotNull(action, "action"); return DEFAULT_ASYNC_EXECUTOR.execute(new Try.Runnable() { @Override public void run() throws E { action.accept(Stream.this); } }); } /** * * @param action a terminal operation should be called. * @param executor * @return */ public ContinuableFuture asyncRun(final Try.Consumer, E> action, final Executor executor) { checkArgNotNull(action, "action"); checkArgNotNull(executor, "executor"); return ContinuableFuture.run(new Try.Runnable() { @Override public void run() throws E { action.accept(Stream.this); } }, executor); } /** * * @param action a terminal operation should be called. * @return */ public ContinuableFuture asyncCall(final Try.Function, R, E> action) { checkArgNotNull(action, "action"); return DEFAULT_ASYNC_EXECUTOR.execute(new Try.Callable() { @Override public R call() throws E { return action.apply(Stream.this); } }); } /** * * @param action a terminal operation should be called. * @param executor * @return */ public ContinuableFuture asyncCall(final Try.Function, R, E> action, final Executor executor) { checkArgNotNull(action, "action"); checkArgNotNull(executor, "executor"); return ContinuableFuture.call(new Try.Callable() { @Override public R call() throws E { return action.apply(Stream.this); } }, executor); } @SequentialOnly @Override public R __(Function, R> transfer) { return transfer.apply(this); } /** * To reduce the memory footprint, Only one instance of DisposableEntry is created, * and the same entry instance is returned and set with different keys/values during iteration of the returned stream. * The elements only can be retrieved one by one, can't be modified or saved. * The returned Stream doesn't support the operations which require two or more elements at the same time: (e.g. sort/distinct/pairMap/slidingMap/sliding/split/toList/toSet/...). * , and can't be parallel stream. * Operations: filter/map/toMap/groupBy/groupTo/... are supported. * * * @param keyMapper * @param valueMapper * @return * * @see DisposableEntry * @see NoCachingNoUpdating * * @deprecated */ @Deprecated @SequentialOnly @Beta public abstract Stream> mapToDisposableEntry(Function keyMapper, Function valueMapper); public static Stream empty() { return new ArrayStream<>((T[]) N.EMPTY_OBJECT_ARRAY, true, NATURAL_COMPARATOR, null); } public static Stream just(final T a) { return of(N.asArray(a)); } public static Stream ofNullable(T t) { return t == null ? Stream. empty() : of(t); } @SafeVarargs public static Stream of(final T... a) { return N.isNullOrEmpty(a) ? (Stream) empty() : of(a, 0, a.length); } /** * * @param a * @param startIndex * @param endIndex * @return */ public static Stream of(final T[] a, final int startIndex, final int endIndex) { return N.isNullOrEmpty(a) && (startIndex == 0 && endIndex == 0) ? (Stream) empty() : new ArrayStream<>(a, startIndex, endIndex); } /** * * @param c * @return */ public static Stream of(final Collection c) { return N.isNullOrEmpty(c) ? (Stream) empty() : of(c, 0, c.size()); } /** * * @param c * @param startIndex * @param endIndex * @return */ public static Stream of(final Collection c, int startIndex, int endIndex) { N.checkFromToIndex(startIndex, endIndex, N.size(c)); if (N.isNullOrEmpty(c) && (startIndex == 0 && endIndex == 0)) { return empty(); } // return new CollectionStream(c); // return new ArrayStream((T[]) c.toArray()); // faster if (isListElementDataFieldGettable && listElementDataField != null && c instanceof ArrayList) { T[] array = null; try { array = (T[]) listElementDataField.get(c); } catch (Throwable e) { // ignore; isListElementDataFieldGettable = false; } if (array != null) { return of(array, startIndex, endIndex); } } if (startIndex == 0 && endIndex == c.size()) { // return (c.size() > 10 && (c.size() < 1000 || (c.size() < 100000 && c instanceof ArrayList))) ? streamOf((T[]) c.toArray()) : c.stream(); return of(ObjIteratorEx.of(c)); } else { return of(ObjIteratorEx.of(c), startIndex, endIndex); } } public static Stream> of(final Map map) { if (N.isNullOrEmpty(map)) { return empty(); } return of(map.entrySet()); } public static Stream of(final Iterable iterable) { if (iterable == null) { return Stream. empty(); } else if (iterable instanceof Collection) { return of((Collection) iterable); } else { return of(iterable.iterator()); } } /** * * @param iterator * @return */ public static Stream of(final Iterator iterator) { if (iterator == null) { return empty(); } return new IteratorStream<>(iterator); } /** * * @param c * @param startIndex * @param endIndex * @return */ static Stream of(final Iterator iterator, int startIndex, int endIndex) { if (iterator == null && (startIndex == 0 && endIndex == 0)) { return empty(); } if (startIndex < 0 || endIndex < startIndex) { throw new IllegalArgumentException("startIndex(" + startIndex + ") or endIndex(" + endIndex + ") is invalid"); } return Stream. of(iterator).skip(startIndex).limit(endIndex - startIndex); } public static Stream of(final java.util.stream.Stream stream) { return of(new ObjIteratorEx() { private Iterator iter = null; @Override public boolean hasNext() { if (iter == null) { iter = stream.iterator(); } return iter.hasNext(); } @Override public T next() { if (iter == null) { iter = stream.iterator(); } return iter.next(); } @Override public long count() { return iter == null ? stream.count() : super.count(); } @Override public void skip(long n) { if (iter == null) { iter = stream.skip(n).iterator(); } else { super.skip(n); } } @Override public Object[] toArray() { return iter == null ? stream.toArray() : super.toArray(); } @Override public
A[] toArray(final A[] a) { return iter == null ? stream.toArray(new IntFunction() { @Override public A[] apply(int value) { return a; } }) : super.toArray(a); } }).__(s -> stream.isParallel() ? s.parallel() : s.sequential()).onClose(new Runnable() { @Override public void run() { stream.close(); } }); } public static Stream of(final boolean[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final boolean[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Boolean next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Boolean.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(char[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final char[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Character next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Character.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(byte[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final byte[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Byte next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Byte.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(short[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final short[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Short next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Short.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(int[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final int[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Integer next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Integer.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(long[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final long[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Long next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Long.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(float[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final float[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Float next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Float.valueOf(a[cursor++]); } return a2; } }); } public static Stream of(double[] a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(a, 0, a.length); } public static Stream of(final double[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, N.len(a)); if (N.isNullOrEmpty(a)) { return empty(); } return of(new ObjIteratorEx() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public Double next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public long count() { return toIndex - cursor; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cursor = n < toIndex - cursor ? cursor + (int) n : toIndex; } @Override public A[] toArray(A[] a2) { a2 = a2.length >= toIndex - cursor ? a2 : (A[]) N.newArray(a2.getClass().getComponentType(), toIndex - cursor); for (int i = 0, len = toIndex - cursor; i < len; i++) { a2[i] = (A) Double.valueOf(a[cursor++]); } return a2; } }); } /** * Lazy evaluation. * @param supplier * @return */ public static Stream of(final Supplier> supplier) { final Iterator iter = new ObjIteratorEx() { private Iterator iterator = null; @Override public boolean hasNext() { if (iterator == null) { init(); } return iterator.hasNext(); } @Override public T next() { if (iterator == null) { init(); } return iterator.next(); } private void init() { final Collection c = supplier.get(); if (N.isNullOrEmpty(c)) { iterator = ObjIterator.empty(); } else { iterator = c.iterator(); } } }; return of(iter); } public static Stream ofKeys(Map map) { if (map == null || map.size() == 0) { return Stream.empty(); } return of(map.keySet()); } public static Stream ofKeys(Map map, Predicate valueFilter) { if (map == null || map.size() == 0) { return StreamEx.empty(); } return EntryStream.of(map).filterByValue(valueFilter).keys(); } public static Stream ofValues(Map map) { if (map == null || map.size() == 0) { return Stream.empty(); } return of(map.values()); } public static Stream ofValues(Map map, Predicate keyFilter) { if (map == null || map.size() == 0) { return Stream.empty(); } return EntryStream.of(map).filterByKey(keyFilter).values(); } public static Stream flat(final Collection> c) { return of(c).flattMap(Fn.> identity()); } public static Stream flat(final T[][] a) { return of(a).flatMapp(Fn. identity()); } public static Stream flat(final T[][] a, final boolean vertically) { if (N.isNullOrEmpty(a)) { return empty(); } else if (a.length == 1) { return of(a[0]); } else if (vertically == false) { return of(a).flatMapp(Fn. identity()); } long n = 0; for (T[] e : a) { n += N.len(e); } if (n == 0) { return empty(); } final int rows = N.len(a); final long count = n; final Iterator iter = new ObjIteratorEx() { private int rowNum = 0; private int colNum = 0; private long cnt = 0; @Override public boolean hasNext() { return cnt < count; } @Override public T next() { 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 Stream flat(final T[][] a, final T 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 (T[] 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 = rows * cols; Iterator iter = null; if (vertically) { iter = new ObjIteratorEx() { private int rowNum = 0; private int colNum = 0; private long cnt = 0; @Override public boolean hasNext() { return cnt < count; } @Override public T next() { 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 ObjIteratorEx() { private int rowNum = 0; private int colNum = 0; private long cnt = 0; @Override public boolean hasNext() { return cnt < count; } @Override public T next() { 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 Stream flat(final T[][][] a) { return of(a).flatMapp(e -> e).flatMapp(Fn. identity()); } public static Stream repeat(final T element, final long n) { N.checkArgNotNegative(n, "n"); if (n == 0) { return empty(); } return new IteratorStream<>(new ObjIteratorEx() { private long cnt = n; @Override public boolean hasNext() { return cnt > 0; } @Override public T next() { if (cnt-- <= 0) { throw new NoSuchElementException(); } return element; } @Override public void skip(long n) { N.checkArgNotNegative(n, "n"); cnt = n >= cnt ? 0 : cnt - (int) n; } @Override public long count() { return cnt; } @Override public A[] toArray(A[] a) { a = a.length >= cnt ? a : N.copyOf(a, (int) cnt); for (int i = 0; i < cnt; i++) { a[i] = (A) element; } cnt = 0; return a; } }); } public static Stream iterate(final BooleanSupplier hasNext, final Supplier next) { N.checkArgNotNull(hasNext); N.checkArgNotNull(next); return of(new ObjIteratorEx() { private boolean hasNextVal = false; @Override public boolean hasNext() { if (hasNextVal == false) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } hasNextVal = false; return next.get(); } }); } /** * Returns a sequential ordered {@code Stream} produced by iterative * application of a function {@code f} to an initial element {@code init}, * producing a {@code Stream} consisting of {@code init}, {@code f(init)}, * {@code f(f(init))}, etc. * *

The first element (position {@code 0}) in the {@code Stream} will be * the provided {@code init}. For {@code n > 0}, the element at position * {@code n}, will be the result of applying the function {@code f} to the * element at position {@code n - 1}. * * @param init * @param hasNext * @param f * @return */ public static Stream iterate(final T init, final BooleanSupplier hasNext, final UnaryOperator f) { N.checkArgNotNull(hasNext); N.checkArgNotNull(f); return of(new ObjIteratorEx() { private T t = (T) NONE; private boolean hasNextVal = false; @Override public boolean hasNext() { if (hasNextVal == false) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } hasNextVal = false; return t = (t == NONE) ? init : f.apply(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 Stream iterate(final T init, final Predicate hasNext, final UnaryOperator f) { N.checkArgNotNull(hasNext); N.checkArgNotNull(f); return of(new ObjIteratorEx() { private T t = (T) NONE; private T cur = (T) NONE; private boolean hasMore = true; private boolean hasNextVal = false; @Override public boolean hasNext() { if (hasNextVal == false && hasMore) { hasNextVal = hasNext.test((cur = (t == NONE ? init : f.apply(t)))); if (hasNextVal == false) { hasMore = false; } } return hasNextVal; } @Override public T next() { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } t = cur; cur = (T) NONE; hasNextVal = false; return t; } }); } public static Stream iterate(final T init, final UnaryOperator f) { N.checkArgNotNull(f); return of(new ObjIteratorEx() { private T t = (T) NONE; @Override public boolean hasNext() { return true; } @Override public T next() { return t = t == NONE ? init : f.apply(t); } }); } public static Stream generate(final Supplier s) { N.checkArgNotNull(s); return of(new ObjIteratorEx() { @Override public boolean hasNext() { return true; } @Override public T next() { return s.get(); } }); } /** * * @param intervalInMillis * @param s * @return */ public static Stream interval(final long intervalInMillis, final Supplier s) { return interval(0, intervalInMillis, s); } /** * * @param delayInMillis * @param intervalInMillis * @param s * @return * @see java.util.concurrent.TimeUnit */ public static Stream interval(final long delayInMillis, final long intervalInMillis, final Supplier s) { return interval(delayInMillis, intervalInMillis, TimeUnit.MILLISECONDS, s); } /** * * @param delay * @param interval * @param unit * @param s * @return */ public static Stream interval(final long delay, final long interval, final TimeUnit unit, final Supplier s) { N.checkArgNotNull(s); return LongStream.interval(delay, interval, unit).mapToObj(new LongFunction() { @Override public T apply(long value) { return s.get(); } }); } public static Stream interval(final long intervalInMillis, final LongFunction s) { return interval(0, intervalInMillis, s); } /** * * @param delayInMillis * @param intervalInMillis * @param s * @return * @see java.util.concurrent.TimeUnit */ public static Stream interval(final long delayInMillis, final long intervalInMillis, final LongFunction s) { return interval(delayInMillis, intervalInMillis, TimeUnit.MILLISECONDS, s); } /** * * @param delay * @param interval * @param unit * @param s * @return */ public static Stream interval(final long delay, final long interval, final TimeUnit unit, final LongFunction s) { N.checkArgNotNull(s); return LongStream.interval(delay, interval, unit).mapToObj(s); } public static Stream lines(final File file) { return lines(file, Charsets.UTF_8); } public static Stream lines(final File file, final Charset charset) { final ObjIteratorEx iter = createLazyLineIterator(file, null, charset, null, true); return of(iter).onClose(new Runnable() { @Override public void run() { iter.close(); } }); } public static Stream lines(final Path path) { return lines(path, Charsets.UTF_8); } public static Stream lines(final Path path, final Charset charset) { final ObjIteratorEx iter = createLazyLineIterator(null, path, charset, null, true); return of(iter).onClose(new Runnable() { @Override public void run() { iter.close(); } }); } /** * It's user's responsibility to close the input reader after the stream is finished. * * @param reader * @return */ public static Stream lines(final Reader reader) { N.checkArgNotNull(reader); return of(createLazyLineIterator(null, null, Charsets.UTF_8, reader, false)); } private static ObjIteratorEx createLazyLineIterator(final File file, final Path path, final Charset charset, final Reader reader, final boolean closeReader) { return ObjIteratorEx.of(new Supplier>() { private ObjIteratorEx lazyIter = null; @Override public synchronized ObjIteratorEx get() { if (lazyIter == null) { lazyIter = new ObjIteratorEx() { private BufferedReader bufferedReader; { if (reader != null) { bufferedReader = reader instanceof BufferedReader ? ((BufferedReader) reader) : new BufferedReader(reader); } else if (file != null) { bufferedReader = IOUtil.newBufferedReader(file, charset == null ? Charsets.UTF_8 : charset); } else { bufferedReader = IOUtil.newBufferedReader(path, charset == null ? Charsets.UTF_8 : charset); } } private final LineIterator lineIterator = new LineIterator(bufferedReader); @Override public boolean hasNext() { return lineIterator.hasNext(); } @Override public String next() { return lineIterator.next(); } @Override public void close() { if (closeReader) { IOUtil.closeQuietly(reader); } } }; } return lazyIter; } }); } public static Stream listFiles(final File parentPath) { if (!parentPath.exists()) { return empty(); } return of(parentPath.listFiles()); } public static Stream listFiles(final File parentPath, final boolean recursively) { if (!parentPath.exists()) { return empty(); } else if (recursively == false) { return of(parentPath.listFiles()); } final ObjIterator iter = new ObjIterator() { private final Queue paths = N.asLinkedList(parentPath); private File[] subFiles = null; private int cursor = 0; @Override public boolean hasNext() { if ((subFiles == null || cursor >= subFiles.length) && paths.size() > 0) { cursor = 0; subFiles = null; while (paths.size() > 0) { subFiles = paths.poll().listFiles(); if (N.notNullOrEmpty(subFiles)) { break; } } } return subFiles != null && cursor < subFiles.length; } @Override public File next() { if (hasNext() == false) { throw new NoSuchElementException(); } if (subFiles[cursor].isDirectory()) { paths.offer(subFiles[cursor]); } return subFiles[cursor++]; } }; return of(iter); } public static Stream observe(final BlockingQueue queue, final Duration duration) { return observe(queue, duration, Fn.emptyAction()); } /** * Sample code: * *

     * 
     * final BlockingQueue queue = new ArrayBlockingQueue<>(32);
     * Stream.observe(queue, Duration.ofMillis(100)).filter(s -> s.startsWith("a")).asyncRun(s -> s.forEach(Fn.println()));
     * N.asList("a", "b", "ab", "bc", "1", "a").forEach(queue::add);
     * N.sleep(10);
     * N.println("==================");
     * N.sleep(100);
     * N.println("==================");
     * N.sleep(10);
     * 
     * 
* * @param queue * @param duration * @param onComplete * @return */ public static Stream observe(final BlockingQueue queue, final Duration duration, final Runnable onComplete) { N.checkArgNotNull(queue, "queue"); N.checkArgNotNull(duration, "duration"); N.checkArgNotNull(onComplete, "onComplete"); final long now = System.currentTimeMillis(); final long endTime = duration.toMillis() >= Long.MAX_VALUE - now ? Long.MAX_VALUE : now + duration.toMillis(); final Iterator iter = new ObjIterator() { private T next = null; @Override public boolean hasNext() { if (next == null) { final long curTime = System.currentTimeMillis(); if (curTime <= endTime) { try { next = queue.poll(endTime - curTime, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new RuntimeException(e); } } } return next != null; } @Override public T next() { if (hasNext() == false) { throw new NoSuchElementException(); } final T res = next; next = null; return res; } }; return of(iter).onClose(onComplete); } public static Stream observe(final BlockingQueue queue, final BooleanSupplier hasMore, final long maxWaitIntervalInMillis) { return observe(queue, hasMore, maxWaitIntervalInMillis, Fn.emptyAction()); } /** * Sample code: * *
     * 
     * final BlockingQueue queue = new ArrayBlockingQueue<>(32);
     * final MutableBoolean hasMore = MutableBoolean.of(true);
     * Stream.observe(queue, () -> hasMore.value(), 10).filter(s -> s.startsWith("a")).asyncRun(s -> s.forEach(Fn.println()));
     * N.asList("a", "b", "ab", "bc", "1", "a").forEach(queue::add);
     * N.println("==================");
     * hasMore.setFalse();
     * N.sleep(50);
     * N.println("==================");
     * 
     * 
* * @param queue * @param hasMore * @param maxWaitIntervalInMillis * @param isCompleted it will will be set to {@code true} if Stream is completed and the upstream should not continue to put elements to queue when it's completed. * This is an output parameter. * @return */ public static Stream observe(final BlockingQueue queue, final BooleanSupplier hasMore, final long maxWaitIntervalInMillis, final Runnable onComplete) { N.checkArgNotNull(queue, "queue"); N.checkArgNotNull(hasMore, "hasMore"); N.checkArgPositive(maxWaitIntervalInMillis, "maxWaitIntervalInMillis"); N.checkArgNotNull(onComplete, "onComplete"); final Iterator iter = new ObjIterator() { private T next = null; @Override public boolean hasNext() { if (next == null && (hasMore.getAsBoolean() || queue.size() > 0)) { try { do { next = queue.poll(maxWaitIntervalInMillis, TimeUnit.MILLISECONDS); } while (next == null && (hasMore.getAsBoolean() || queue.size() > 0)); } catch (InterruptedException e) { throw new RuntimeException(e); } } return next != null; } @Override public T next() { if (hasNext() == false) { throw new NoSuchElementException(); } final T res = next; next = null; return res; } }; return of(iter).onClose(onComplete); } @SafeVarargs public static Stream concat(final T[]... a) { return N.isNullOrEmpty(a) ? (Stream) empty() : new IteratorStream<>(new ObjIteratorEx() { private final Iterator iter = N.asList(a).iterator(); private Iterator cur; @Override public boolean hasNext() { while ((cur == null || cur.hasNext() == false) && iter.hasNext()) { cur = ObjIteratorEx.of(iter.next()); } return cur != null && cur.hasNext(); } @Override public T next() { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } }); } @SafeVarargs public static Stream concat(final Collection... a) { return N.isNullOrEmpty(a) ? (Stream) empty() : new IteratorStream<>(new ObjIteratorEx() { private final Iterator> iter = N.asList(a).iterator(); private Iterator cur; @Override public boolean hasNext() { while ((cur == null || cur.hasNext() == false) && iter.hasNext()) { cur = iter.next().iterator(); } return cur != null && cur.hasNext(); } @Override public T next() { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } }); } @SafeVarargs public static Stream concat(final Iterator... a) { if (N.isNullOrEmpty(a)) { return empty(); } return concatt(N.asList(a)); } @SafeVarargs public static Stream concat(final Stream... a) { if (N.isNullOrEmpty(a)) { return empty(); } return concat(N.asList(a)); } public static Stream concat(final Collection> c) { if (N.isNullOrEmpty(c)) { return empty(); } return of(new ObjIteratorEx() { private final Iterator> iterators = c.iterator(); private Stream cur; private Iterator iter; @Override public boolean hasNext() { while ((iter == null || iter.hasNext() == false) && iterators.hasNext()) { if (cur != null) { cur.close(); } cur = iterators.next(); iter = cur.iterator(); } return iter != null && iter.hasNext(); } @Override public T next() { if ((iter == null || iter.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return iter.next(); } }).onClose(newCloseHandler(c)); } public static Stream concatt(final Collection> c) { if (N.isNullOrEmpty(c)) { return empty(); } return of(new ObjIteratorEx() { private final Iterator> iterators = c.iterator(); private Iterator cur; @Override public boolean hasNext() { while ((cur == null || cur.hasNext() == false) && iterators.hasNext()) { cur = iterators.next(); } return cur != null && cur.hasNext(); } @Override public T next() { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } }); } // NO NEED. // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelConcat(a,b, ...)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @return // */ // public static Stream parallelConcat(final T[]... a) { // return parallelConcat(a, DEFAULT_READING_THREAD_NUM, calculateQueueSize(a.length)); // } // // /** // * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. // * // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelConcat(a,b, ...)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, a.length) // * @param queueSize Default value is N.min(128, a.length * 16) // * @return // */ // public static Stream parallelConcat(final T[][] a, final int readThreadNum, final int queueSize) { // if (N.isNullOrEmpty(a)) { // return empty(); // } // // final Iterator[] iters = new Iterator[a.length]; // // for (int i = 0, len = a.length; i < len; i++) { // iters[i] = ImmutableIterator.of(a[i]); // } // // return parallelConcat(iters, readThreadNum, queueSize); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelConcat(a,b, ...)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @return // */ // public static Stream parallelConcat(final Collection... a) { // return parallelConcat(a, DEFAULT_READING_THREAD_NUM, calculateQueueSize(a.length)); // } // // /** // * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. // * // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelConcat(a,b, ...)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, a.length) // * @param queueSize Default value is N.min(128, a.length * 16) // * @return // */ // public static Stream parallelConcat(final Collection[] a, final int readThreadNum, final int queueSize) { // if (N.isNullOrEmpty(a)) { // return empty(); // } // // final Iterator[] iters = new Iterator[a.length]; // // for (int i = 0, len = a.length; i < len; i++) { // iters[i] = a[i].iterator(); // } // // return parallelConcat(iters, readThreadNum, queueSize); // } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @return */ @SafeVarargs public static Stream parallelConcat(final Iterator... a) { return parallelConcat(a, DEFAULT_READING_THREAD_NUM, calculateQueueSize(a.length)); } /** * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. * * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, a.length) * @param queueSize Default value is N.min(128, a.length * 16) * @return */ public static Stream parallelConcat(final Iterator[] a, final int readThreadNum, final int queueSize) { if (N.isNullOrEmpty(a)) { return empty(); } return parallelConcatt(N.asList(a), readThreadNum, queueSize); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @return */ @SafeVarargs public static Stream parallelConcat(final Stream... a) { return parallelConcat(a, DEFAULT_READING_THREAD_NUM, calculateQueueSize(a.length)); } /** * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. * * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, a.length) * @param queueSize Default value is N.min(128, a.length * 16) * @return */ public static Stream parallelConcat(final Stream[] a, final int readThreadNum, final int queueSize) { if (N.isNullOrEmpty(a)) { return empty(); } return parallelConcat(N.asList(a), readThreadNum, queueSize); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param c * @return */ public static Stream parallelConcat(final Collection> c) { return parallelConcat(c, DEFAULT_READING_THREAD_NUM); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param c * @param readThreadNum * @return */ public static Stream parallelConcat(final Collection> c, final int readThreadNum) { return parallelConcat(c, readThreadNum, calculateQueueSize(c.size())); } /** * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. * * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, c.size()) * @param queueSize Default value is N.min(128, c.size() * 16) * @return */ public static Stream parallelConcat(final Collection> c, final int readThreadNum, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final AtomicInteger threadCounter = new AtomicInteger(c.size()); final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); final MutableBoolean disposableChecked = MutableBoolean.of(false); final Iterator> iterators = c.iterator(); final int threadNum = Math.min(c.size(), readThreadNum); for (int i = 0; i < threadNum; i++) { DEFAULT_ASYNC_EXECUTOR.execute(new Try.Runnable() { @Override public void run() { try { while (onGoing.value()) { Stream s = null; Iterator iter = null; synchronized (iterators) { if (iterators.hasNext()) { s = iterators.next(); iter = s.iterator(); } else { break; } } T next = null; while (onGoing.value() && iter.hasNext()) { next = iter.next(); if (next == null) { next = (T) NONE; } else if (disposableChecked.isFalse()) { disposableChecked.setTrue(); if (next instanceof NoCachingNoUpdating) { throw new RuntimeException("Can't run NoCachingNoUpdating Objects in parallel Stream or Queue"); } } if (queue.offer(next) == false) { while (onGoing.value()) { if (queue.offer(next, 100, TimeUnit.MILLISECONDS)) { break; } } } } if (s != null) { s.close(); } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounter.decrementAndGet(); } } }); } return of(new QueuedIterator(queueSize) { T next = null; @Override public boolean hasNext() { try { if (next == null && (next = queue.poll()) == null) { while (onGoing.value() && (threadCounter.get() > 0 || queue.size() > 0)) { // (queue.size() > 0 || counter.get() > 0) is wrong. has to check counter first if ((next = queue.poll(1, TimeUnit.MILLISECONDS)) != null) { break; } } } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } return next != null; } @Override public T next() { if (next == null && hasNext() == false) { throw new NoSuchElementException(); } T result = next == NONE ? null : next; next = null; return result; } }).onClose(newCloseHandler(c)).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param c * @return */ public static Stream parallelConcatt(final Collection> c) { return parallelConcatt(c, DEFAULT_READING_THREAD_NUM); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param c * @param readThreadNum * @return */ public static Stream parallelConcatt(final Collection> c, final int readThreadNum) { return parallelConcatt(c, readThreadNum, calculateQueueSize(c.size())); } /** * Returns a Stream with elements from a temporary queue which is filled by reading the elements from the specified iterators in parallel. * * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelConcat(a,b, ...)) { * stream.forEach(N::println); * } * * * @param a * @param readThreadNum - count of threads used to read elements from iterator to queue. Default value is min(8, c.size()) * @param queueSize Default value is N.min(128, c.size() * 16) * @return */ public static Stream parallelConcatt(final Collection> c, final int readThreadNum, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final AtomicInteger threadCounter = new AtomicInteger(c.size()); final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); final MutableBoolean disposableChecked = MutableBoolean.of(false); final Iterator> iterators = c.iterator(); final int threadNum = Math.min(c.size(), readThreadNum); for (int i = 0; i < threadNum; i++) { DEFAULT_ASYNC_EXECUTOR.execute(new Try.Runnable() { @Override public void run() { try { while (onGoing.value()) { Iterator iter = null; synchronized (iterators) { if (iterators.hasNext()) { iter = iterators.next(); } else { break; } } T next = null; while (onGoing.value() && iter.hasNext()) { next = iter.next(); if (next == null) { next = (T) NONE; } else if (disposableChecked.isFalse()) { disposableChecked.setTrue(); if (next instanceof NoCachingNoUpdating) { throw new RuntimeException("Can't run NoCachingNoUpdating Objects in parallel Stream or Queue"); } } if (queue.offer(next) == false) { while (onGoing.value()) { if (queue.offer(next, 100, TimeUnit.MILLISECONDS)) { break; } } } } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounter.decrementAndGet(); } } }); } return of(new QueuedIterator(queueSize) { T next = null; @Override public boolean hasNext() { try { if (next == null && (next = queue.poll()) == null) { while (onGoing.value() && (threadCounter.get() > 0 || queue.size() > 0)) { // (queue.size() > 0 || counter.get() > 0) is wrong. has to check counter first if ((next = queue.poll(1, TimeUnit.MILLISECONDS)) != null) { break; } } } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } return next != null; } @Override public T next() { if (next == null && hasNext() == false) { throw new NoSuchElementException(); } T result = next == NONE ? null : next; next = null; return result; } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } /** * 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 Stream zip(final char[] a, final char[] b, final CharBiFunction zipFunction) { return zip(CharIteratorEx.of(a), CharIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final char[] a, final char[] b, final char[] c, final CharTriFunction zipFunction) { return zip(CharIteratorEx.of(a), CharIteratorEx.of(b), CharIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final CharIterator a, final CharIterator b, final CharBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextChar(), b.nextChar()); } }); } /** * 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 Stream zip(final CharIterator a, final CharIterator b, final CharIterator c, final CharTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextChar(), b.nextChar(), c.nextChar()); } }); } /** * 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 Stream zip(final CharStream a, final CharStream b, final CharBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final CharStream a, final CharStream b, final CharStream c, final CharTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final CharNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final CharIterator[] iters = new CharIterator[len]; int i = 0; for (CharStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final char[] args = new char[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextChar(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final char[] a, final char[] b, final char valueForNoneA, final char valueForNoneB, final CharBiFunction zipFunction) { return zip(CharIteratorEx.of(a), CharIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final char[] a, final char[] b, final char[] c, final char valueForNoneA, final char valueForNoneB, final char valueForNoneC, final CharTriFunction zipFunction) { return zip(CharIteratorEx.of(a), CharIteratorEx.of(b), CharIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final CharIterator a, final CharIterator b, final char valueForNoneA, final char valueForNoneB, final CharBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextChar() : valueForNoneA, b.hasNext() ? b.nextChar() : valueForNoneB); } }); } /** * 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 Stream zip(final CharIterator a, final CharIterator b, final CharIterator c, final char valueForNoneA, final char valueForNoneB, final char valueForNoneC, final CharTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextChar() : valueForNoneA, b.hasNext() ? b.nextChar() : valueForNoneB, c.hasNext() ? c.nextChar() : valueForNoneC); } }); } /** * 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 Stream zip(final CharStream a, final CharStream b, final char valueForNoneA, final char valueForNoneB, final CharBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final CharStream a, final CharStream b, final CharStream c, final char valueForNoneA, final char valueForNoneB, final char valueForNoneC, final CharTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final char[] valuesForNone, final CharNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final CharStream[] ss = c.toArray(new CharStream[len]); final CharIterator[] iters = new CharIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final char[] args = new char[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextChar(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final byte[] a, final byte[] b, final ByteBiFunction zipFunction) { return zip(ByteIteratorEx.of(a), ByteIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final byte[] a, final byte[] b, final byte[] c, final ByteTriFunction zipFunction) { return zip(ByteIteratorEx.of(a), ByteIteratorEx.of(b), ByteIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final ByteIterator a, final ByteIterator b, final ByteBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextByte(), b.nextByte()); } }); } /** * 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 Stream zip(final ByteIterator a, final ByteIterator b, final ByteIterator c, final ByteTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextByte(), b.nextByte(), c.nextByte()); } }); } /** * 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 Stream zip(final ByteStream a, final ByteStream b, final ByteBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final ByteStream a, final ByteStream b, final ByteStream c, final ByteTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final ByteNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final ByteIterator[] iters = new ByteIterator[len]; int i = 0; for (ByteStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final byte[] args = new byte[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextByte(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final byte[] a, final byte[] b, final byte valueForNoneA, final byte valueForNoneB, final ByteBiFunction zipFunction) { return zip(ByteIteratorEx.of(a), ByteIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final byte[] a, final byte[] b, final byte[] c, final byte valueForNoneA, final byte valueForNoneB, final byte valueForNoneC, final ByteTriFunction zipFunction) { return zip(ByteIteratorEx.of(a), ByteIteratorEx.of(b), ByteIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final ByteIterator a, final ByteIterator b, final byte valueForNoneA, final byte valueForNoneB, final ByteBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextByte() : valueForNoneA, b.hasNext() ? b.nextByte() : valueForNoneB); } }); } /** * 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 Stream zip(final ByteIterator a, final ByteIterator b, final ByteIterator c, final byte valueForNoneA, final byte valueForNoneB, final byte valueForNoneC, final ByteTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextByte() : valueForNoneA, b.hasNext() ? b.nextByte() : valueForNoneB, c.hasNext() ? c.nextByte() : valueForNoneC); } }); } /** * 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 Stream zip(final ByteStream a, final ByteStream b, final byte valueForNoneA, final byte valueForNoneB, final ByteBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final ByteStream a, final ByteStream b, final ByteStream c, final byte valueForNoneA, final byte valueForNoneB, final byte valueForNoneC, final ByteTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final byte[] valuesForNone, final ByteNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final ByteStream[] ss = c.toArray(new ByteStream[len]); final ByteIterator[] iters = new ByteIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final byte[] args = new byte[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextByte(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final short[] a, final short[] b, final ShortBiFunction zipFunction) { return zip(ShortIteratorEx.of(a), ShortIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final short[] a, final short[] b, final short[] c, final ShortTriFunction zipFunction) { return zip(ShortIteratorEx.of(a), ShortIteratorEx.of(b), ShortIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final ShortIterator a, final ShortIterator b, final ShortBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextShort(), b.nextShort()); } }); } /** * 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 Stream zip(final ShortIterator a, final ShortIterator b, final ShortIterator c, final ShortTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextShort(), b.nextShort(), c.nextShort()); } }); } /** * 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 Stream zip(final ShortStream a, final ShortStream b, final ShortBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final ShortStream a, final ShortStream b, final ShortStream c, final ShortTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final ShortNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final ShortIterator[] iters = new ShortIterator[len]; int i = 0; for (ShortStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final short[] args = new short[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextShort(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final short[] a, final short[] b, final short valueForNoneA, final short valueForNoneB, final ShortBiFunction zipFunction) { return zip(ShortIteratorEx.of(a), ShortIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final short[] a, final short[] b, final short[] c, final short valueForNoneA, final short valueForNoneB, final short valueForNoneC, final ShortTriFunction zipFunction) { return zip(ShortIteratorEx.of(a), ShortIteratorEx.of(b), ShortIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final ShortIterator a, final ShortIterator b, final short valueForNoneA, final short valueForNoneB, final ShortBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextShort() : valueForNoneA, b.hasNext() ? b.nextShort() : valueForNoneB); } }); } /** * 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 Stream zip(final ShortIterator a, final ShortIterator b, final ShortIterator c, final short valueForNoneA, final short valueForNoneB, final short valueForNoneC, final ShortTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextShort() : valueForNoneA, b.hasNext() ? b.nextShort() : valueForNoneB, c.hasNext() ? c.nextShort() : valueForNoneC); } }); } /** * 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 Stream zip(final ShortStream a, final ShortStream b, final short valueForNoneA, final short valueForNoneB, final ShortBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final ShortStream a, final ShortStream b, final ShortStream c, final short valueForNoneA, final short valueForNoneB, final short valueForNoneC, final ShortTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final short[] valuesForNone, final ShortNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final ShortStream[] ss = c.toArray(new ShortStream[len]); final ShortIterator[] iters = new ShortIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final short[] args = new short[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextShort(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final int[] a, final int[] b, final IntBiFunction zipFunction) { return zip(IntIteratorEx.of(a), IntIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final int[] a, final int[] b, final int[] c, final IntTriFunction zipFunction) { return zip(IntIteratorEx.of(a), IntIteratorEx.of(b), IntIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final IntIterator a, final IntIterator b, final IntBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextInt(), b.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 * @return */ public static Stream zip(final IntIterator a, final IntIterator b, final IntIterator c, final IntTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextInt(), b.nextInt(), c.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 * @return */ public static Stream zip(final IntStream a, final IntStream b, final IntBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final IntStream a, final IntStream b, final IntStream c, final IntTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final IntNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final IntIterator[] iters = new IntIterator[len]; int i = 0; for (IntStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final int[] args = new int[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextInt(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final int[] a, final int[] b, final int valueForNoneA, final int valueForNoneB, final IntBiFunction zipFunction) { return zip(IntIteratorEx.of(a), IntIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final int[] a, final int[] b, final int[] c, final int valueForNoneA, final int valueForNoneB, final int valueForNoneC, final IntTriFunction zipFunction) { return zip(IntIteratorEx.of(a), IntIteratorEx.of(b), IntIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final IntIterator a, final IntIterator b, final int valueForNoneA, final int valueForNoneB, final IntBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextInt() : valueForNoneA, b.hasNext() ? b.nextInt() : valueForNoneB); } }); } /** * 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 Stream zip(final IntIterator a, final IntIterator b, final IntIterator c, final int valueForNoneA, final int valueForNoneB, final int valueForNoneC, final IntTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextInt() : valueForNoneA, b.hasNext() ? b.nextInt() : valueForNoneB, c.hasNext() ? c.nextInt() : valueForNoneC); } }); } /** * 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 Stream zip(final IntStream a, final IntStream b, final int valueForNoneA, final int valueForNoneB, final IntBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final IntStream a, final IntStream b, final IntStream c, final int valueForNoneA, final int valueForNoneB, final int valueForNoneC, final IntTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final int[] valuesForNone, final IntNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final IntStream[] ss = c.toArray(new IntStream[len]); final IntIterator[] iters = new IntIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final int[] args = new int[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextInt(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final long[] a, final long[] b, final LongBiFunction zipFunction) { return zip(LongIteratorEx.of(a), LongIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final long[] a, final long[] b, final long[] c, final LongTriFunction zipFunction) { return zip(LongIteratorEx.of(a), LongIteratorEx.of(b), LongIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final LongIterator a, final LongIterator b, final LongBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextLong(), b.nextLong()); } }); } /** * 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 Stream zip(final LongIterator a, final LongIterator b, final LongIterator c, final LongTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextLong(), b.nextLong(), c.nextLong()); } }); } /** * 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 Stream zip(final LongStream a, final LongStream b, final LongBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final LongStream a, final LongStream b, final LongStream c, final LongTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final LongNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final LongIterator[] iters = new LongIterator[len]; int i = 0; for (LongStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final long[] args = new long[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextLong(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final long[] a, final long[] b, final long valueForNoneA, final long valueForNoneB, final LongBiFunction zipFunction) { return zip(LongIteratorEx.of(a), LongIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final long[] a, final long[] b, final long[] c, final long valueForNoneA, final long valueForNoneB, final long valueForNoneC, final LongTriFunction zipFunction) { return zip(LongIteratorEx.of(a), LongIteratorEx.of(b), LongIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final LongIterator a, final LongIterator b, final long valueForNoneA, final long valueForNoneB, final LongBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextLong() : valueForNoneA, b.hasNext() ? b.nextLong() : valueForNoneB); } }); } /** * 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 Stream zip(final LongIterator a, final LongIterator b, final LongIterator c, final long valueForNoneA, final long valueForNoneB, final long valueForNoneC, final LongTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextLong() : valueForNoneA, b.hasNext() ? b.nextLong() : valueForNoneB, c.hasNext() ? c.nextLong() : valueForNoneC); } }); } /** * 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 Stream zip(final LongStream a, final LongStream b, final long valueForNoneA, final long valueForNoneB, final LongBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final LongStream a, final LongStream b, final LongStream c, final long valueForNoneA, final long valueForNoneB, final long valueForNoneC, final LongTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final long[] valuesForNone, final LongNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final LongStream[] ss = c.toArray(new LongStream[len]); final LongIterator[] iters = new LongIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final long[] args = new long[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextLong(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final float[] a, final float[] b, final FloatBiFunction zipFunction) { return zip(FloatIteratorEx.of(a), FloatIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final float[] a, final float[] b, final float[] c, final FloatTriFunction zipFunction) { return zip(FloatIteratorEx.of(a), FloatIteratorEx.of(b), FloatIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final FloatIterator a, final FloatIterator b, final FloatBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextFloat(), b.nextFloat()); } }); } /** * 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 Stream zip(final FloatIterator a, final FloatIterator b, final FloatIterator c, final FloatTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextFloat(), b.nextFloat(), c.nextFloat()); } }); } /** * 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 Stream zip(final FloatStream a, final FloatStream b, final FloatBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final FloatStream a, final FloatStream b, final FloatStream c, final FloatTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final FloatNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final FloatIterator[] iters = new FloatIterator[len]; int i = 0; for (FloatStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final float[] args = new float[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextFloat(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final float[] a, final float[] b, final float valueForNoneA, final float valueForNoneB, final FloatBiFunction zipFunction) { return zip(FloatIteratorEx.of(a), FloatIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final float[] a, final float[] b, final float[] c, final float valueForNoneA, final float valueForNoneB, final float valueForNoneC, final FloatTriFunction zipFunction) { return zip(FloatIteratorEx.of(a), FloatIteratorEx.of(b), FloatIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final FloatIterator a, final FloatIterator b, final float valueForNoneA, final float valueForNoneB, final FloatBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextFloat() : valueForNoneA, b.hasNext() ? b.nextFloat() : valueForNoneB); } }); } /** * 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 Stream zip(final FloatIterator a, final FloatIterator b, final FloatIterator c, final float valueForNoneA, final float valueForNoneB, final float valueForNoneC, final FloatTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextFloat() : valueForNoneA, b.hasNext() ? b.nextFloat() : valueForNoneB, c.hasNext() ? c.nextFloat() : valueForNoneC); } }); } /** * 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 Stream zip(final FloatStream a, final FloatStream b, final float valueForNoneA, final float valueForNoneB, final FloatBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final FloatStream a, final FloatStream b, final FloatStream c, final float valueForNoneA, final float valueForNoneB, final float valueForNoneC, final FloatTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final float[] valuesForNone, final FloatNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final FloatStream[] ss = c.toArray(new FloatStream[len]); final FloatIterator[] iters = new FloatIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final float[] args = new float[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextFloat(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final double[] a, final double[] b, final DoubleBiFunction zipFunction) { return zip(DoubleIteratorEx.of(a), DoubleIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final double[] a, final double[] b, final double[] c, final DoubleTriFunction zipFunction) { return zip(DoubleIteratorEx.of(a), DoubleIteratorEx.of(b), DoubleIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final DoubleIterator a, final DoubleIterator b, final DoubleBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextDouble(), b.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 Stream zip(final DoubleIterator a, final DoubleIterator b, final DoubleIterator c, final DoubleTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.nextDouble(), b.nextDouble(), c.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 Stream zip(final DoubleStream a, final DoubleStream b, final DoubleBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final DoubleStream a, final DoubleStream b, final DoubleStream c, final DoubleTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), zipFunction).onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final DoubleNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final DoubleIterator[] iters = new DoubleIterator[len]; int i = 0; for (DoubleStream s : c) { iters[i++] = s.iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final double[] args = new double[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].nextDouble(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final double[] a, final double[] b, final double valueForNoneA, final double valueForNoneB, final DoubleBiFunction zipFunction) { return zip(DoubleIteratorEx.of(a), DoubleIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final double[] a, final double[] b, final double[] c, final double valueForNoneA, final double valueForNoneB, final double valueForNoneC, final DoubleTriFunction zipFunction) { return zip(DoubleIteratorEx.of(a), DoubleIteratorEx.of(b), DoubleIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final DoubleIterator a, final DoubleIterator b, final double valueForNoneA, final double valueForNoneB, final DoubleBiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextDouble() : valueForNoneA, b.hasNext() ? b.nextDouble() : valueForNoneB); } }); } /** * 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 Stream zip(final DoubleIterator a, final DoubleIterator b, final DoubleIterator c, final double valueForNoneA, final double valueForNoneB, final double valueForNoneC, final DoubleTriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.nextDouble() : valueForNoneA, b.hasNext() ? b.nextDouble() : valueForNoneB, c.hasNext() ? c.nextDouble() : valueForNoneC); } }); } /** * 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 Stream zip(final DoubleStream a, final DoubleStream b, final double valueForNoneA, final double valueForNoneB, final DoubleBiFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final DoubleStream a, final DoubleStream b, final DoubleStream c, final double valueForNoneA, final double valueForNoneB, final double valueForNoneC, final DoubleTriFunction zipFunction) { return zip(a.iteratorEx(), b.iteratorEx(), c.iteratorEx(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.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 */ @SuppressWarnings("resource") public static Stream zip(final Collection c, final double[] valuesForNone, final DoubleNFunction zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.length) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final DoubleStream[] ss = c.toArray(new DoubleStream[len]); final DoubleIterator[] iters = new DoubleIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final double[] args = new double[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].nextDouble(); } else { args[i] = valuesForNone[i]; } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(args); } }).onClose(newCloseHandler(c)); } /** * 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 Stream zip(final A[] a, final B[] b, final BiFunction zipFunction) { return zip(ObjIteratorEx.of(a), ObjIteratorEx.of(b), zipFunction); } /** * 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 * @return */ public static Stream zip(final A[] a, final B[] b, final C[] c, final TriFunction zipFunction) { return zip(ObjIteratorEx.of(a), ObjIteratorEx.of(b), ObjIteratorEx.of(c), zipFunction); } /** * 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 Stream zip(final Collection a, final Collection b, final BiFunction zipFunction) { return zip(a.iterator(), b.iterator(), zipFunction); } /** * 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 * @return */ public static Stream zip(final Collection a, final Collection b, final Collection c, final TriFunction zipFunction) { return zip(a.iterator(), b.iterator(), c.iterator(), zipFunction); } /** * 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 Stream zip(final Iterator a, final Iterator b, final BiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext(); } @Override public R next() { return zipFunction.apply(a.next(), b.next()); } }); } /** * 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 Stream zip(final Iterator a, final Iterator b, final Iterator c, final TriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() && b.hasNext() && c.hasNext(); } @Override public R next() { return zipFunction.apply(a.next(), b.next(), c.next()); } }); } /** * 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 Stream zip(final Stream a, final Stream b, final BiFunction zipFunction) { return zip(a.iterator(), b.iterator(), zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final Stream a, final Stream b, final Stream c, final TriFunction zipFunction) { return zip(a.iterator(), b.iterator(), c.iterator(), zipFunction).onClose(newCloseHandler(N.asList(a, b, c))); } public static Stream zip(final List> c, final Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final List> iterList = new ArrayList<>(len); for (Collection e : c) { iterList.add(ObjIterator.of(e)); } return zipp(iterList, zipFunction); } /** * 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 Stream zip(final Collection> c, final Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final List> iterList = new ArrayList<>(len); for (Stream e : c) { iterList.add(e.iterator()); } return zipp(iterList, zipFunction).onClose(newCloseHandler(c)); } public static Stream zipp(final Collection> c, final Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final Iterator[] iters = c.toArray(new Iterator[len]); return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i].hasNext() == false) { return false; } } return true; } @Override public R next() { final Object[] args = new Object[len]; for (int i = 0; i < len; i++) { args[i] = iters[i].next(); } return zipFunction.apply(Arrays.asList((T[]) args)); } }); } /** * 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 Stream zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return zip(ObjIteratorEx.of(a), ObjIteratorEx.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return zip(ObjIteratorEx.of(a), ObjIteratorEx.of(b), ObjIteratorEx.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final Collection a, final Collection b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return zip(a.iterator(), b.iterator(), valueForNoneA, valueForNoneB, zipFunction); } /** * 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 Stream zip(final Collection a, final Collection b, final Collection c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return zip(a.iterator(), b.iterator(), c.iterator(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * 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 Stream zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.next() : valueForNoneA, b.hasNext() ? b.next() : valueForNoneB); } }); } /** * 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 Stream zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { return a.hasNext() || b.hasNext() || c.hasNext(); } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(a.hasNext() ? a.next() : valueForNoneA, b.hasNext() ? b.next() : valueForNoneB, c.hasNext() ? c.next() : valueForNoneC); } }); } /** * 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 Stream zip(final Stream a, final Stream b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return zip(a.iterator(), b.iterator(), valueForNoneA, valueForNoneB, zipFunction).onClose(newCloseHandler(N.asList(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 Stream zip(final Stream a, final Stream b, final Stream c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return zip(a.iterator(), b.iterator(), c.iterator(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction) .onClose(newCloseHandler(N.asList(a, b, c))); } public static Stream zip(final List> c, final List valuesForNone, Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final List> iterList = new ArrayList<>(len); for (Collection e : c) { iterList.add(e.iterator()); } return zipp(iterList, valuesForNone, zipFunction); } /** * 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 Stream zip(final Collection> c, final List valuesForNone, final Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final Stream[] ss = c.toArray(new Stream[len]); final ObjIterator[] iters = new ObjIterator[len]; for (int i = 0; i < len; i++) { iters[i] = ss[i].iteratorEx(); } return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; ss[i].close(); } } } return false; } @Override public R next() { final Object[] args = new Object[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].next(); } else { args[i] = valuesForNone.get(i); } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(Arrays.asList((T[]) args)); } }); } /** * * @param c * @param valuesForNone value to fill for any iterator runs out of values. * @param zipFunction * @return */ public static Stream zipp(final Collection> c, final List valuesForNone, final Function, R> zipFunction) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final Iterator[] iters = c.toArray(new Iterator[len]); return new IteratorStream<>(new ObjIteratorEx() { @Override public boolean hasNext() { for (int i = 0; i < len; i++) { if (iters[i] != null) { if (iters[i].hasNext()) { return true; } else if (iters[i] != null) { iters[i] = null; } } } return false; } @Override public R next() { final Object[] args = new Object[len]; boolean hasNext = false; for (int i = 0; i < len; i++) { if (iters[i] != null && iters[i].hasNext()) { hasNext = true; args[i] = iters[i].next(); } else { args[i] = valuesForNone.get(i); } } if (hasNext == false) { throw new NoSuchElementException(); } return zipFunction.apply(Arrays.asList((T[]) args)); } }); } // NO NEED. // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param zipFunction // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final BiFunction zipFunction) { // return parallelZip(a, b, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final BiFunction zipFunction, final int queueSize) { // return parallelZip(ImmutableIterator.of(a), ImmutableIterator.of(b), zipFunction, queueSize); // } // // public static Stream parallelZip(final A[] a, final B[] b, final C[] c, final TriFunction zipFunction) { // return parallelZip(a, b, c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final C[] c, final TriFunction zipFunction, // final int queueSize) { // return parallelZip(ImmutableIterator.of(a), ImmutableIterator.of(b), ImmutableIterator.of(c), zipFunction, queueSize); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param zipFunction // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, // final BiFunction zipFunction) { // return parallelZip(a, b, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, // final BiFunction zipFunction, final int queueSize) { // return parallelZip(a.iterator(), b.iterator(), zipFunction, queueSize); // } // // public static Stream parallelZip(final Collection a, final Collection b, final Collection c, // final TriFunction zipFunction) { // return parallelZip(a, b, c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, final Collection c, // final TriFunction zipFunction, final int queueSize) { // return parallelZip(a.iterator(), b.iterator(), c.iterator(), zipFunction, queueSize); // } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param zipFunction * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final BiFunction zipFunction) { return parallelZip(a, b, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final BiFunction zipFunction, final int queueSize) { final AtomicInteger threadCounterA = new AtomicInteger(1); final AtomicInteger threadCounterB = new AtomicInteger(1); final BlockingQueue
queueA = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueB = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); readToQueue(a, b, DEFAULT_ASYNC_EXECUTOR, threadCounterA, threadCounterB, queueA, queueB, eHolder, onGoing); return of(new QueuedIterator(queueSize) { A nextA = null; B nextB = null; @Override public boolean hasNext() { if (nextA == null || nextB == null) { try { while (nextA == null && onGoing.value() && (threadCounterA.get() > 0 || queueA.size() > 0)) { // (threadCounterA.get() > 0 || queueA.size() > 0) is wrong. has to check counter first nextA = queueA.poll(1, TimeUnit.MILLISECONDS); } if (nextA == null) { onGoing.setFalse(); return false; } while (nextB == null && onGoing.value() && (threadCounterB.get() > 0 || queueB.size() > 0)) { // (threadCounterB.get() > 0 || queueB.size() > 0) is wrong. has to check counter first nextB = queueB.poll(1, TimeUnit.MILLISECONDS); } if (nextB == null) { onGoing.setFalse(); return false; } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } return true; } @Override public R next() { if ((nextA == null || nextB == null) && hasNext() == false) { throw new NoSuchElementException(); } boolean isOK = false; try { final R result = zipFunction.apply(nextA == NONE ? null : nextA, nextB == NONE ? null : nextB); nextA = null; nextB = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } public static Stream parallelZip(final Iterator a, final Iterator b, final Iterator c, final TriFunction zipFunction) { return parallelZip(a, b, c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final Iterator c, final TriFunction zipFunction, final int queueSize) { final AtomicInteger threadCounterA = new AtomicInteger(1); final AtomicInteger threadCounterB = new AtomicInteger(1); final AtomicInteger threadCounterC = new AtomicInteger(1); final BlockingQueue
queueA = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueB = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueC = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); readToQueue(a, b, c, DEFAULT_ASYNC_EXECUTOR, threadCounterA, threadCounterB, threadCounterC, queueA, queueB, queueC, eHolder, onGoing); return of(new QueuedIterator(queueSize) { A nextA = null; B nextB = null; C nextC = null; @Override public boolean hasNext() { if (nextA == null || nextB == null || nextC == null) { try { while (nextA == null && onGoing.value() && (threadCounterA.get() > 0 || queueA.size() > 0)) { // (threadCounterA.get() > 0 || queueA.size() > 0) is wrong. has to check counter first nextA = queueA.poll(1, TimeUnit.MILLISECONDS); } if (nextA == null) { onGoing.setFalse(); return false; } while (nextB == null && onGoing.value() && (threadCounterB.get() > 0 || queueB.size() > 0)) { // (threadCounterB.get() > 0 || queueB.size() > 0) is wrong. has to check counter first nextB = queueB.poll(1, TimeUnit.MILLISECONDS); } if (nextB == null) { onGoing.setFalse(); return false; } while (nextC == null && onGoing.value() && (threadCounterC.get() > 0 || queueC.size() > 0)) { // (threadCounterC.get() > 0 || queueC.size() > 0) is wrong. has to check counter first nextC = queueC.poll(1, TimeUnit.MILLISECONDS); } if (nextC == null) { onGoing.setFalse(); return false; } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } return true; } @Override public R next() { if ((nextA == null || nextB == null || nextC == null) && hasNext() == false) { throw new NoSuchElementException(); } boolean isOK = false; try { final R result = zipFunction.apply(nextA == NONE ? null : nextA, nextB == NONE ? null : nextB, nextC == NONE ? null : nextC); nextA = null; nextB = null; nextC = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param zipFunction * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final BiFunction zipFunction) { return parallelZip(a, b, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final BiFunction zipFunction, final int queueSize) { return parallelZip(a.iterator(), b.iterator(), zipFunction, queueSize).onClose(newCloseHandler(N.asList(a, b))); } public static Stream parallelZip(final Stream a, final Stream b, final Stream c, final TriFunction zipFunction) { return parallelZip(a, b, c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final Stream c, final TriFunction zipFunction, final int queueSize) { return parallelZip(a.iterator(), b.iterator(), c.iterator(), zipFunction, queueSize).onClose(newCloseHandler(N.asList(a, b, c))); } public static Stream parallelZip(final List> c, final Function, R> zipFunction) { return parallelZip(c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } public static Stream parallelZip(final List> c, final Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final List> iterList = new ArrayList<>(len); for (Collection e : c) { iterList.add(e.iterator()); } return parallelZipp(iterList, zipFunction, queueSize); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param zipFunction * @return */ public static Stream parallelZip(final Collection> c, final Function, R> zipFunction) { return parallelZip(c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Collection> c, final Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final List> iterList = new ArrayList<>(len); for (Stream e : c) { iterList.add(e.iterator()); } return parallelZipp(iterList, zipFunction, queueSize).onClose(newCloseHandler(c)); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param zipFunction * @return */ public static Stream parallelZipp(final Collection> c, final Function, R> zipFunction) { return parallelZipp(c, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZipp(final Collection> c, final Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); final AtomicInteger[] counters = new AtomicInteger[len]; final BlockingQueue[] queues = new ArrayBlockingQueue[len]; final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); readToQueue(c, queueSize, DEFAULT_ASYNC_EXECUTOR, counters, queues, eHolder, onGoing); return of(new QueuedIterator(queueSize) { Object[] next = null; @Override public boolean hasNext() { if (next == null) { next = new Object[len]; for (int i = 0; i < len; i++) { try { while (next[i] == null && onGoing.value() && (counters[i].get() > 0 || queues[i].size() > 0)) { // (counters[i].get() > 0 || queues[i].size() > 0) is wrong. has to check counter first next[i] = queues[i].poll(1, TimeUnit.MILLISECONDS); } if (next[i] == null) { onGoing.setFalse(); return false; } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } } else { for (int i = 0; i < len; i++) { if (next[i] == null) { return false; } } } return true; } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } for (int i = 0; i < len; i++) { if (next[i] == NONE) { next[i] = null; } } boolean isOK = false; try { R result = zipFunction.apply(Arrays.asList((T[]) next)); next = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } // NO NEED. // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, // final BiFunction zipFunction) { // return parallelZip(a, b, valueForNoneA, valueForNoneB, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, // final BiFunction zipFunction, final int queueSize) { // return parallelZip(ImmutableIterator.of(a), ImmutableIterator.of(b), valueForNoneA, valueForNoneB, zipFunction, queueSize); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, // final TriFunction zipFunction) { // return parallelZip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, // final TriFunction zipFunction, final int queueSize) { // return parallelZip(ImmutableIterator.of(a), ImmutableIterator.of(b), ImmutableIterator.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, queueSize); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, final A valueForNoneA, // final B valueForNoneB, final BiFunction zipFunction) { // return parallelZip(a, b, valueForNoneA, valueForNoneB, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param valueForNoneA // * @param valueForNoneB // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, final A valueForNoneA, // final B valueForNoneB, final BiFunction zipFunction, final int queueSize) { // return parallelZip(a.iterator(), b.iterator(), valueForNoneA, valueForNoneB, zipFunction, queueSize); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, final Collection c, // final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { // return parallelZip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); // } // // /** // * Put the stream in try-catch to stop the back-end reading thread if error happens // *
// * // * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { // * stream.forEach(N::println); // * } // * // * // * @param a // * @param b // * @param c // * @param valueForNoneA // * @param valueForNoneB // * @param valueForNoneC // * @param zipFunction // * @param queueSize for each iterator. Default value is 32 // * @return // */ // public static Stream parallelZip(final Collection a, final Collection b, final Collection c, // final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction, // final int queueSize) { // return parallelZip(a.iterator(), b.iterator(), c.iterator(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, queueSize); // } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return parallelZip(a, b, valueForNoneA, valueForNoneB, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction, final int queueSize) { final AtomicInteger threadCounterA = new AtomicInteger(1); final AtomicInteger threadCounterB = new AtomicInteger(1); final BlockingQueue queueA = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueB = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); readToQueue(a, b, DEFAULT_ASYNC_EXECUTOR, threadCounterA, threadCounterB, queueA, queueB, eHolder, onGoing); return of(new QueuedIterator(queueSize) { A nextA = null; B nextB = null; @Override public boolean hasNext() { if (nextA == null && nextB == null) { try { while (nextA == null && onGoing.value() && (threadCounterA.get() > 0 || queueA.size() > 0)) { // (threadCounterA.get() > 0 || queueA.size() > 0) is wrong. has to check counter first nextA = queueA.poll(1, TimeUnit.MILLISECONDS); } while (nextB == null && onGoing.value() && (threadCounterB.get() > 0 || queueB.size() > 0)) { // (threadCounterB.get() > 0 || queueB.size() > 0) is wrong. has to check counter first nextB = queueB.poll(1, TimeUnit.MILLISECONDS); } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } if (nextA != null || nextB != null) { return true; } else { onGoing.setFalse(); return false; } } @Override public R next() { if ((nextA == null && nextB == null) && hasNext() == false) { throw new NoSuchElementException(); } nextA = nextA == NONE ? null : (nextA == null ? valueForNoneA : nextA); nextB = nextB == NONE ? null : (nextB == null ? valueForNoneB : nextB); boolean isOK = false; try { final R result = zipFunction.apply(nextA, nextB); nextA = null; nextB = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return parallelZip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction, final int queueSize) { final AtomicInteger threadCounterA = new AtomicInteger(1); final AtomicInteger threadCounterB = new AtomicInteger(1); final AtomicInteger threadCounterC = new AtomicInteger(1); final BlockingQueue
queueA = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueB = new ArrayBlockingQueue<>(queueSize); final BlockingQueue queueC = new ArrayBlockingQueue<>(queueSize); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); readToQueue(a, b, c, DEFAULT_ASYNC_EXECUTOR, threadCounterA, threadCounterB, threadCounterC, queueA, queueB, queueC, eHolder, onGoing); return of(new QueuedIterator(queueSize) { A nextA = null; B nextB = null; C nextC = null; @Override public boolean hasNext() { if (nextA == null && nextB == null && nextC == null) { try { while (nextA == null && onGoing.value() && (threadCounterA.get() > 0 || queueA.size() > 0)) { // (threadCounterA.get() > 0 || queueA.size() > 0) is wrong. has to check counter first nextA = queueA.poll(1, TimeUnit.MILLISECONDS); } while (nextB == null && onGoing.value() && (threadCounterB.get() > 0 || queueB.size() > 0)) { // (threadCounterB.get() > 0 || queueB.size() > 0) is wrong. has to check counter first nextB = queueB.poll(1, TimeUnit.MILLISECONDS); } while (nextC == null && onGoing.value() && (threadCounterC.get() > 0 || queueC.size() > 0)) { // (threadCounterC.get() > 0 || queueC.size() > 0) is wrong. has to check counter first nextC = queueC.poll(1, TimeUnit.MILLISECONDS); } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } if (nextA != null || nextB != null || nextC != null) { return true; } else { onGoing.setFalse(); return false; } } @Override public R next() { if ((nextA == null && nextB == null && nextC == null) && hasNext() == false) { throw new NoSuchElementException(); } nextA = nextA == NONE ? null : (nextA == null ? valueForNoneA : nextA); nextB = nextB == NONE ? null : (nextB == null ? valueForNoneB : nextB); nextC = nextC == NONE ? null : (nextC == null ? valueForNoneC : nextC); boolean isOK = false; try { final R result = zipFunction.apply(nextA, nextB, nextC); nextA = null; nextB = null; nextC = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction) { return parallelZip(a, b, valueForNoneA, valueForNoneB, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final A valueForNoneA, final B valueForNoneB, final BiFunction zipFunction, final int queueSize) { return parallelZip(a.iterator(), b.iterator(), valueForNoneA, valueForNoneB, zipFunction, queueSize).onClose(newCloseHandler(N.asList(a, b))); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final Stream c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction) { return parallelZip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param a * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Stream
a, final Stream b, final Stream c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final TriFunction zipFunction, final int queueSize) { return parallelZip(a.iterator(), b.iterator(), c.iterator(), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction, queueSize) .onClose(newCloseHandler(N.asList(a, b, c))); } public static Stream parallelZip(final List> c, final List valuesForNone, Function, R> zipFunction) { return parallelZip(c, valuesForNone, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } public static Stream parallelZip(final List> c, final List valuesForNone, Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final List> iterList = new ArrayList<>(len); for (Collection e : c) { iterList.add(e.iterator()); } return parallelZipp(iterList, valuesForNone, zipFunction, queueSize); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param valuesForNone * @param zipFunction * @return */ public static Stream parallelZip(final Collection> c, final List valuesForNone, Function, R> zipFunction) { return parallelZip(c, valuesForNone, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param valuesForNone * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZip(final Collection> c, final List valuesForNone, Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } final int len = c.size(); if (len != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final List> iterList = new ArrayList<>(len); for (Stream e : c) { iterList.add(e.iterator()); } return parallelZipp(iterList, valuesForNone, zipFunction, queueSize).onClose(newCloseHandler(c)); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param valuesForNone * @param zipFunction * @return */ public static Stream parallelZipp(final Collection> c, final List valuesForNone, Function, R> zipFunction) { return parallelZipp(c, valuesForNone, zipFunction, DEFAULT_QUEUE_SIZE_PER_ITERATOR); } /** * Put the stream in try-catch to stop the back-end reading thread if error happens *
* * try (Stream stream = Stream.parallelZip(a, b, zipFunction)) { * stream.forEach(N::println); * } * * * @param c * @param valuesForNone * @param zipFunction * @param queueSize for each iterator. Default value is 32 * @return */ public static Stream parallelZipp(final Collection> c, final List valuesForNone, final Function, R> zipFunction, final int queueSize) { if (N.isNullOrEmpty(c)) { return Stream.empty(); } if (c.size() != valuesForNone.size()) { throw new IllegalArgumentException("The size of 'valuesForNone' must be same as the size of the collection of iterators"); } final int len = c.size(); final Holder eHolder = new Holder<>(); final MutableBoolean onGoing = MutableBoolean.of(true); final AtomicInteger[] counters = new AtomicInteger[len]; final BlockingQueue[] queues = new ArrayBlockingQueue[len]; readToQueue(c, queueSize, DEFAULT_ASYNC_EXECUTOR, counters, queues, eHolder, onGoing); return of(new QueuedIterator(queueSize) { Object[] next = null; @Override public boolean hasNext() { if (next == null) { next = new Object[len]; for (int i = 0; i < len; i++) { try { while (next[i] == null && onGoing.value() && (counters[i].get() > 0 || queues[i].size() > 0)) { // (counters[i].get() > 0 || queues[i].size() > 0) is wrong. has to check counter first next[i] = queues[i].poll(1, TimeUnit.MILLISECONDS); } } catch (Exception e) { setError(eHolder, e, onGoing); } if (eHolder.value() != null) { throwError(eHolder, onGoing); } } } for (int i = 0; i < len; i++) { if (next[i] != null) { return true; } } onGoing.setFalse(); return false; } @Override public R next() { if (hasNext() == false) { throw new NoSuchElementException(); } for (int i = 0; i < len; i++) { next[i] = next[i] == NONE ? null : (next[i] == null ? valuesForNone.get(i) : next[i]); } boolean isOK = false; try { R result = zipFunction.apply(Arrays.asList((T[]) next)); next = null; isOK = true; return result; } finally { // error happened if (isOK == false) { onGoing.setFalse(); } } } }).onClose(new Runnable() { @Override public void run() { onGoing.setFalse(); } }); } // /** // * // * @param c // * @param unzip the second parameter is an output parameter. // * @return // */ // public static Pair, Stream> unzip(final Collection c, final BiConsumer> unzip) { // final Pair, List> p = Seq.unzip(c, unzip); // // return Pair.of(Stream.of(p.left), Stream.of(p.right)); // } // // /** // * // * @param iter // * @param unzip the second parameter is an output parameter. // * @return // */ // public static Pair, Stream> unzip(final Iterator iter, final BiConsumer> unzip) { // final Pair, List> p = Iterators.unzip(iter, unzip); // // return Pair.of(Stream.of(p.left), Stream.of(p.right)); // } // // /** // * // * @param c // * @param unzip the second parameter is an output parameter. // * @return // */ // public static Triple, Stream, Stream> unzipp(final Collection c, // final BiConsumer> unzip) { // final Triple, List, List> p = Seq.unzipp(c, unzip); // // return Triple.of(Stream.of(p.left), Stream.of(p.middle), Stream.of(p.right)); // } // // /** // * // * @param iter // * @param unzip the second parameter is an output parameter. // * @return // */ // public static Triple, Stream, Stream> unzipp(final Iterator iter, // final BiConsumer> unzip) { // final Triple, List, List> p = Iterators.unzipp(iter, unzip); // // return Triple.of(Stream.of(p.left), Stream.of(p.middle), Stream.of(p.right)); // } /** * * @param a * @param b * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static Stream merge(final T[] a, final T[] b, final BiFunction nextSelector) { if (N.isNullOrEmpty(a)) { return of(b); } else if (N.isNullOrEmpty(b)) { return of(a); } return new IteratorStream<>(new ObjIteratorEx() { 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 T next() { if (cursorA < lenA) { if (cursorB < lenB) { if (nextSelector.apply(a[cursorA], b[cursorB]) == Nth.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 Stream merge(final T[] a, final T[] b, final T[] c, final BiFunction nextSelector) { return merge(merge(a, b, nextSelector).iterator(), Stream.of(c).iterator(), 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 Stream merge(final Collection a, final Collection b, final BiFunction nextSelector) { return merge(a.iterator(), b.iterator(), nextSelector); } /** * * @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 Stream merge(final Collection a, final Collection b, final Collection c, final BiFunction nextSelector) { return merge(a.iterator(), b.iterator(), c.iterator(), 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 Stream merge(final Iterator a, final Iterator b, final BiFunction nextSelector) { return new IteratorStream<>(new ObjIteratorEx() { private T nextA = null; private T nextB = null; private boolean hasNextA = false; private boolean hasNextB = false; @Override public boolean hasNext() { return hasNextA || hasNextB || a.hasNext() || b.hasNext(); } @Override public T next() { if (hasNextA) { if (b.hasNext()) { if (nextSelector.apply(nextA, (nextB = b.next())) == Nth.FIRST) { hasNextA = false; hasNextB = true; return nextA; } else { return nextB; } } else { hasNextA = false; return nextA; } } else if (hasNextB) { if (a.hasNext()) { if (nextSelector.apply((nextA = a.next()), nextB) == Nth.FIRST) { return nextA; } else { hasNextA = true; hasNextB = false; return nextB; } } else { hasNextB = false; return nextB; } } else if (a.hasNext()) { if (b.hasNext()) { if (nextSelector.apply((nextA = a.next()), (nextB = b.next())) == Nth.FIRST) { hasNextB = true; return nextA; } else { hasNextA = true; return nextB; } } else { return a.next(); } } else if (b.hasNext()) { return b.next(); } 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 Stream merge(final Iterator a, final Iterator b, final Iterator c, final BiFunction nextSelector) { return merge(merge(a, b, nextSelector).iterator(), 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 Stream merge(final Stream a, final Stream b, final BiFunction nextSelector) { return merge(a.iterator(), b.iterator(), nextSelector).onClose(newCloseHandler(N.asList(a, b))); } public static Stream merge(final Stream a, final Stream b, final Stream c, final BiFunction nextSelector) { return merge(merge(a, b, nextSelector), c, nextSelector); } public static Stream merge(final List> c, final BiFunction nextSelector) { N.checkArgNotNull(nextSelector); if (N.isNullOrEmpty(c)) { return empty(); } else if (c.size() == 1) { return of(c.iterator().next()); } else if (c.size() == 2) { final Iterator> iter = c.iterator(); return merge(iter.next(), iter.next(), nextSelector); } final List> iterList = new ArrayList<>(c.size()); for (Collection e : c) { iterList.add(e.iterator()); } return mergge(iterList, nextSelector); } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static Stream merge(final Collection> c, final BiFunction nextSelector) { N.checkArgNotNull(nextSelector); if (N.isNullOrEmpty(c)) { return empty(); } else if (c.size() == 1) { return (Stream) 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(); Stream result = merge(iter.next(), iter.next(), nextSelector); while (iter.hasNext()) { result = merge(result, iter.next(), nextSelector); } return result; } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static Stream mergge(final Collection> c, final BiFunction nextSelector) { N.checkArgNotNull(nextSelector); if (N.isNullOrEmpty(c)) { return empty(); } else if (c.size() == 1) { return of(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(); Stream result = merge(iter.next(), iter.next(), nextSelector); while (iter.hasNext()) { result = merge(result.iterator(), iter.next(), nextSelector); } return result; } public static Stream parallelMerge(final List> c, final BiFunction nextSelector) { return parallelMerge(c, nextSelector, DEFAULT_MAX_THREAD_NUM); } public static Stream parallelMerge(final List> c, final BiFunction nextSelector, final int maxThreadNum) { N.checkArgNotNull(nextSelector); if (maxThreadNum <= 1) { return merge(c, nextSelector); } else if (N.isNullOrEmpty(c)) { return empty(); } else if (c.size() == 1) { return of(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 List> iterList = new ArrayList<>(c.size()); for (Collection e : c) { iterList.add(e.iterator()); } return parallelMergge(iterList, nextSelector, maxThreadNum); } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static Stream parallelMerge(final Collection> c, final BiFunction nextSelector) { return parallelMerge(c, nextSelector, DEFAULT_MAX_THREAD_NUM); } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @param maxThreadNum * @return */ public static Stream parallelMerge(final Collection> c, final BiFunction 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 (Stream) c.iterator().next(); } else if (c.size() == 2) { final Iterator> iter = c.iterator(); return merge(iter.next().queued(), iter.next().queued(), nextSelector); } else if (c.size() == 3) { final Iterator> iter = c.iterator(); return merge(iter.next().queued(), iter.next().queued(), iter.next().queued(), nextSelector); } final Queue> queue = N.newLinkedList(); for (Stream e : c) { queue.add((Stream) e); } final Holder eHolder = new Holder<>(); final MutableInt cnt = MutableInt.of(c.size()); final List> futureList = new ArrayList<>(c.size() - 1); for (int i = 0, n = N.min(maxThreadNum, c.size() / 2 + 1); i < n; i++) { futureList.add(DEFAULT_ASYNC_EXECUTOR.execute(new Try.Runnable() { @Override public void run() { Stream a = null; Stream b = null; Stream c = 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; } } c = Stream.of((T[]) merge(a, b, nextSelector).toArray()); synchronized (queue) { queue.offer(c); } } } catch (Exception e) { setError(eHolder, e); } } })); } try { complete(futureList, eHolder); } finally { if (eHolder.value() != null) { IOUtil.closeAllQuietly(c); } } return merge(queue.poll(), queue.poll(), nextSelector); } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static Stream parallelMergge(final Collection> c, final BiFunction nextSelector) { return parallelMergge(c, nextSelector, DEFAULT_MAX_THREAD_NUM); } /** * * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @param maxThreadNum * @return */ public static Stream parallelMergge(final Collection> c, final BiFunction nextSelector, final int maxThreadNum) { N.checkArgument(maxThreadNum > 0, "'maxThreadNum' must not less than 1"); if (maxThreadNum <= 1) { return mergge(c, nextSelector); } else if (N.isNullOrEmpty(c)) { return empty(); } else if (c.size() == 1) { return of(c.iterator().next()); } else if (c.size() == 2) { final Iterator> iter = c.iterator(); final Iterator a = iter.next(); final Iterator b = iter.next(); return merge(a instanceof QueuedIterator ? a : Stream.of(a).queued().iterator(), b instanceof QueuedIterator ? b : Stream.of(b).queued().iterator(), nextSelector); } else if (c.size() == 3) { final Iterator> iter = c.iterator(); final Iterator iterA = iter.next(); final Iterator iterB = iter.next(); final Iterator iterC = iter.next(); return merge(iterA instanceof QueuedIterator ? iterA : Stream.of(iterA).queued().iterator(), iterB instanceof QueuedIterator ? iterB : Stream.of(iterB).queued().iterator(), iterC instanceof QueuedIterator ? iterC : Stream.of(iterC).queued().iterator(), nextSelector); } final Queue> queue = N.newLinkedList(c); final Holder eHolder = new Holder<>(); final MutableInt cnt = MutableInt.of(c.size()); final List> futureList = new ArrayList<>(c.size() - 1); for (int i = 0, n = N.min(maxThreadNum, c.size() / 2 + 1); i < n; i++) { futureList.add(DEFAULT_ASYNC_EXECUTOR.execute(new Try.Runnable() { @Override public void run() { Iterator a = null; Iterator b = null; Iterator c = 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; } } c = (Iterator) ObjIteratorEx.of(merge(a instanceof QueuedIterator ? a : Stream.of(a).queued().iterator(), b instanceof QueuedIterator ? b : Stream.of(b).queued().iterator(), nextSelector).toArray()); synchronized (queue) { queue.offer(c); } } } catch (Exception e) { setError(eHolder, e); } } })); } complete(futureList, eHolder); final Iterator a = queue.poll(); final Iterator b = queue.poll(); return merge(a instanceof QueuedIterator ? a : Stream.of(a).queued().iterator(), b instanceof QueuedIterator ? b : Stream.of(b).queued().iterator(), nextSelector); } private static void readToQueue(final Iterator a, final Iterator b, final AsyncExecutor asyncExecutor, final AtomicInteger threadCounterA, final AtomicInteger threadCounterB, final BlockingQueue queueA, final BlockingQueue queueB, final Holder eHolder, final MutableBoolean onGoing) { asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { A nextA = null; while (onGoing.value() && a.hasNext()) { nextA = a.next(); if (nextA == null) { nextA = (A) NONE; } while (onGoing.value() && queueA.offer(nextA, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounterA.decrementAndGet(); } } }); asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { B nextB = null; while (onGoing.value() && b.hasNext()) { nextB = b.next(); if (nextB == null) { nextB = (B) NONE; } while (onGoing.value() && queueB.offer(nextB, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounterB.decrementAndGet(); } } }); } private static void readToQueue(final Iterator a, final Iterator b, final Iterator c, final AsyncExecutor asyncExecutor, final AtomicInteger threadCounterA, final AtomicInteger threadCounterB, final AtomicInteger threadCounterC, final BlockingQueue queueA, final BlockingQueue queueB, final BlockingQueue queueC, final Holder eHolder, final MutableBoolean onGoing) { asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { A nextA = null; while (onGoing.value() && a.hasNext()) { nextA = a.next(); if (nextA == null) { nextA = (A) NONE; } while (onGoing.value() && queueA.offer(nextA, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounterA.decrementAndGet(); } } }); asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { B nextB = null; while (onGoing.value() && b.hasNext()) { nextB = b.next(); if (nextB == null) { nextB = (B) NONE; } while (onGoing.value() && queueB.offer(nextB, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounterB.decrementAndGet(); } } }); asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { C nextC = null; while (onGoing.value() && c.hasNext()) { nextC = c.next(); if (nextC == null) { nextC = (C) NONE; } while (onGoing.value() && queueC.offer(nextC, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { threadCounterC.decrementAndGet(); } } }); } private static void readToQueue(final Collection> c, final int queueSize, final AsyncExecutor asyncExecutor, final AtomicInteger[] counters, final BlockingQueue[] queues, final Holder eHolder, final MutableBoolean onGoing) { int idx = 0; for (Iterator e : c) { counters[idx] = new AtomicInteger(1); queues[idx] = new ArrayBlockingQueue<>(queueSize); final Iterator iter = e; final AtomicInteger count = counters[idx]; final BlockingQueue queue = queues[idx]; asyncExecutor.execute(new Try.Runnable() { @Override public void run() { try { Object next = null; while (onGoing.value() && iter.hasNext()) { next = iter.next(); if (next == null) { next = NONE; } while (onGoing.value() && queue.offer(next, 100, TimeUnit.MILLISECONDS) == false) { // continue } } } catch (Exception e) { setError(eHolder, e, onGoing); } finally { count.decrementAndGet(); } } }); idx++; } } public static abstract class StreamEx extends Stream { private StreamEx(boolean sorted, Comparator cmp, Collection closeHandlers) { super(sorted, cmp, closeHandlers); // Factory class. } } /** * SOO = Sequential Only Operations. * These operations run sequentially only, even under parallel stream. * * Mostly, if an operation is a single operation, or has to be executed in order, * or there is no benefit to execute it in parallel, it will run sequentially, even under parallel stream. * */ public static enum SOO { split, splitToList, splitToSet, splitAt, splitBy, sliding, slidingToList, // intersection, difference, symmetricDifference, // reversed, shuffled, rotated, distinct, hasDuplicates, // append, prepend, indexed, skip, skipLast, limit, step, // join, queued, merge, persist, // combinations, permutations, orderedPermutations, percentiles, cartesianProduct, // collapse, rangeMap, scan, intersperse, top, kthLargest, last, // count, findFirstOrLast, findFirstAndLast, // toArray, toList, toSet, toMultiset, toLongMultiset, toMatrix, toDataSet, // boxed, iterator, asIntStream, asLongStream, asFloatStream, asDoubleStream, // select, println, onClosed, close; } /** * PSO = Parallel supported Operations. * These operations run in parallel under parallel stream. * * Mostly, if an operation can be executed in parallel and has benefit to execute it in parallel. it will run in parallel under parallel stream. * * @author haiyangl * */ public static enum PSO { map, slidingMap, mapToEntry, mapTo_, mapFirst, mapFirstOrElse, mapLast, mapLastOrElse, // flatMap, flattMap, flatMapp, flatMapTo_, // filter, takeWhile, dropWhile, removeIf, skipNull, // sorted, reverseSorted, distinctBy, distinct_filter, peek, peekFirst, peekLast, // groupBy, groupByEntry, groupTo, partitionBy, partitionByToEntry, paritionTo, countBy, countByToEntry, // min, minBy, max, maxBy, sumInt, sumLong, sumDouble, averageInt, averageLong, averageDouble, // toMap, toMulitmap, summerize, summerizze, // forEach, forEachPair, forEachTriple, anyMatch, allMatch, noneMatch, findFirst, findLast, findAny, // reduce, collect, innerJoin, fullJoin, leftJoin, rightJoin, zipWith; } /** * LAIO = Loading All Intermediate Operations. * * Intermediate operations which will load or go through all the elements in the stream. *
* These operation are stateful intermediate operations, which means that subsequent operations no longer operate on the backing collection/iterator, but on an internal state. * */ public static enum LAIO { sorted, sortedBy, reverseSorted, resversed, shuffled, rotated, last_n, // groupBy, groupByToEntity, partitionBy, partitionByToEntity, countBy, countByToEntry; // // HEADD, TAILL, HEAD_AND_TAILL; } }