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

com.landawn.abacus.util.ExceptionalStream Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

The newest version!
/*
 * Copyright (C) 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;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileWriter;
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.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.BaseStream;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.StreamSupport;

import com.landawn.abacus.DataSet;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.IntermediateOp;
import com.landawn.abacus.annotation.LazyEvaluation;
import com.landawn.abacus.annotation.SequentialOnly;
import com.landawn.abacus.annotation.TerminalOp;
import com.landawn.abacus.annotation.TerminalOpTriggered;
import com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.Fn.Factory;
import com.landawn.abacus.util.Fn.Fnn;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.If.OrElse;
import com.landawn.abacus.util.StringUtil.Strings;
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.BinaryOperator;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.stream.Collector;
import com.landawn.abacus.util.stream.Collectors;

/**
 * The Stream will be automatically closed after execution(A terminal method is executed/triggered).
 *
 * @author Haiyang Li
 * @param 
 * @param 
 * @since 1.3
 *
 * @see BaseStream
 * @see Stream
 * @see IntStream
 * @see LongStream
 * @see DoubleStream
 * @see Collectors
 * @see com.landawn.abacus.util.Fn.Fnn
 * @see com.landawn.abacus.util.Comparators
 * @see com.landawn.abacus.util.ExceptionUtil
 */
@LazyEvaluation
@SequentialOnly
@com.landawn.abacus.annotation.Immutable
public class ExceptionalStream implements Closeable, Immutable {

    static final Logger logger = LoggerFactory.getLogger(ExceptionalStream.class);

    static final Random RAND = new SecureRandom();

    static final Throwables.Function, Object>, Object, Exception> KK = new Throwables.Function, Object>, Object, Exception>() {
        @Override
        public Object apply(Map.Entry, Object> t) throws Exception {
            return t.getKey().val();
        }
    };

    private final ExceptionalIterator elements;

    private final boolean sorted;

    private final Comparator cmp;

    private final Deque> closeHandlers;

    private boolean isClosed = false;

    ExceptionalStream(final ExceptionalIterator iter) {
        this(iter, false, null, null);
    }

    ExceptionalStream(final ExceptionalIterator iter, final Deque> closeHandlers) {
        this(iter, false, null, closeHandlers);
    }

    ExceptionalStream(final ExceptionalIterator iter, final boolean sorted, final Comparator comparator,
            final Deque> closeHandlers) {
        this.elements = iter;
        this.sorted = sorted;
        this.cmp = comparator;
        this.closeHandlers = closeHandlers;
    }

    /**
     *
     * @param 
     * @param 
     * @return
     */
    public static  ExceptionalStream empty() {
        return new ExceptionalStream<>(ExceptionalIterator.EMPTY);
    }

    /**
     *
     * @param 
     * @param 
     * @param e
     * @return
     */
    public static  ExceptionalStream just(final T e) {
        return of(e);
    }

    /**
     *
     * @param 
     * @param 
     * @param e
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream just(final T e, @SuppressWarnings("unused") final Class exceptionType) {
        return of(e);
    }

    /**
     * Returns an empty {@code Stream} if the specified {@code t} is null.
     *
     * @param 
     * @param 
     * @param e
     * @return
     */
    public static  ExceptionalStream ofNullable(final T e) {
        if (e == null) {
            return empty();
        }

        return of(e);
    }

    /**
     *
     * @param 
     * @param 
     * @param a
     * @return
     */
    public static  ExceptionalStream of(final T... a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public T next() throws E {
                if (position >= len) {
                    throw new NoSuchElementException();
                }

                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    /**
     *
     * @param 
     * @param 
     * @param c
     * @return
     */
    public static  ExceptionalStream of(final Collection c) {
        if (N.isNullOrEmpty(c)) {
            return empty();
        }

        @SuppressWarnings("deprecation")
        final T[] a = (T[]) InternalUtil.getInternalArray(c);

        if (a != null) {
            final int len = c.size();

            return newStream(new ExceptionalIterator() {
                private int position = 0;

                @Override
                public boolean hasNext() throws E {
                    return position < len;
                }

                @Override
                public T next() throws E {
                    if (position >= len) {
                        throw new NoSuchElementException();
                    }

                    return a[position++];
                }

                @Override
                public long count() throws E {
                    return len - position;
                }

                @Override
                public void advance(long n) throws E {
                    if (n > len - position) {
                        position = len;
                    } else {
                        position += n;
                    }
                }
            });
        }

        return of(c.iterator());
    }

    /**
     *
     * @param 
     * @param 
     * @param iter
     * @return
     */
    public static  ExceptionalStream of(final Iterator iter) {
        if (iter == null) {
            return empty();
        }

        return newStream(ExceptionalIterator. wrap(iter));
    }

    /**
     *
     * @param 
     * @param 
     * @param iterable
     * @return
     */
    public static  ExceptionalStream of(final Iterable iterable) {
        if (iterable == null) {
            return empty();
        }

        if (iterable instanceof Collection) {
            return of((Collection) iterable);
        } else {
            return of(iterable.iterator());
        }
    }

    /**
     *
     * @param  the key type
     * @param  the value type
     * @param 
     * @param m
     * @return
     */
    public static  ExceptionalStream, E> of(final Map m) {
        if (N.isNullOrEmpty(m)) {
            return empty();
        }

        return of(m.entrySet());
    }

    /**
     *
     * @param 
     * @param 
     * @param c
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream of(final Collection c,
            @SuppressWarnings("unused") final Class exceptionType) {
        return of(c);
    }

    /**
     *
     * @param 
     * @param 
     * @param iter
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream of(final Iterator iter,
            @SuppressWarnings("unused") final Class exceptionType) {
        return of(iter);
    }

    /**
     *
     * @param 
     * @param 
     * @param iterable
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream of(final Iterable iterable,
            @SuppressWarnings("unused") final Class exceptionType) {
        return of(iterable);
    }

    /**
     *
     * @param  the key type
     * @param  the value type
     * @param 
     * @param m
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream, E> of(final Map m,
            @SuppressWarnings("unused") final Class exceptionType) {
        return of(m);
    }

    public static  ExceptionalStream of(final boolean[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Boolean next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    public static  ExceptionalStream of(final char[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Character next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    public static  ExceptionalStream of(final byte[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Byte next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    public static  ExceptionalStream of(final short[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Short next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    /**
     *
     * @param 
     * @param a
     * @return
     */
    public static  ExceptionalStream of(final int[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Integer next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    /**
     *
     * @param 
     * @param a
     * @return
     */
    public static  ExceptionalStream of(final long[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Long next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    public static  ExceptionalStream of(final float[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Float next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    /**
     *
     * @param 
     * @param a
     * @return
     */
    public static  ExceptionalStream of(final double[] a) {
        if (N.isNullOrEmpty(a)) {
            return empty();
        }

        final int len = N.len(a);

        return newStream(new ExceptionalIterator() {
            private int position = 0;

            @Override
            public boolean hasNext() throws E {
                return position < len;
            }

            @Override
            public Double next() throws E {
                return a[position++];
            }

            @Override
            public long count() throws E {
                return len - position;
            }

            @Override
            public void advance(long n) throws E {
                if (n > len - position) {
                    position = len;
                } else {
                    position += n;
                }
            }
        });
    }

    public static  ExceptionalStream of(final Optional op) {
        return op == null || !op.isPresent() ? ExceptionalStream. empty() : ExceptionalStream. of(op.get());
    }

    public static  ExceptionalStream of(final java.util.Optional op) {
        return op == null || !op.isPresent() ? ExceptionalStream. empty() : ExceptionalStream. of(op.get());
    }

    /**
     * Lazy evaluation.
     * 
* * This is equal to: {@code ExceptionalStream.just(supplier).flattMap(it -> it.get())}. * * @param supplier * @return */ @Beta public static ExceptionalStream of(final Throwables.Supplier, ? extends E> supplier) { N.checkArgNotNull(supplier, "supplier"); return ExceptionalStream., ? extends E>, E> just(supplier) .flattMap(new Throwables.Function, ? extends E>, Collection, E>() { @Override public Collection apply(Throwables.Supplier, ? extends E> t) throws E { return t.get(); } }); } /** * Lazy evaluation. *
* * This is equal to: {@code ExceptionalStream.just(supplier).flatMap(it -> it.get())}. * * @param supplier * @return */ public static ExceptionalStream from( final Throwables.Supplier, ? extends E> supplier) { N.checkArgNotNull(supplier, "supplier"); return ExceptionalStream., ? extends E>, E> just(supplier) .flatMap( new Throwables.Function, ? extends E>, ExceptionalStream, E>() { @Override public ExceptionalStream apply( Throwables.Supplier, ? extends E> t) throws E { return t.get(); } }); } public static ExceptionalStream ofKeys(final Map map) { if (N.isNullOrEmpty(map)) { return empty(); } return of(map.keySet()); } public static ExceptionalStream ofKeys(final Map map, final Throwables.Predicate valueFilter) { if (N.isNullOrEmpty(map)) { return empty(); } return ExceptionalStream. of(map).filter(Fnn. testByValue(valueFilter)).map(Fnn. key()); } public static ExceptionalStream ofKeys(final Map map, final Throwables.BiPredicate filter) { if (N.isNullOrEmpty(map)) { return empty(); } return ExceptionalStream. of(map).filter(Fn.Entries.ep(filter)).map(Fnn. key()); } public static ExceptionalStream ofValues(final Map map) { if (N.isNullOrEmpty(map)) { return empty(); } return of(map.values()); } public static ExceptionalStream ofValues(final Map map, final Throwables.Predicate keyFilter) { if (N.isNullOrEmpty(map)) { return empty(); } return ExceptionalStream. of(map).filter(Fnn. testByKey(keyFilter)).map(Fnn. value()); } public static ExceptionalStream ofValues(final Map map, final Throwables.BiPredicate filter) { if (N.isNullOrEmpty(map)) { return empty(); } return ExceptionalStream. of(map).filter(Fn.Entries.ep(filter)).map(Fnn. value()); } /** * * @param * @param * @param hasNext * @param next * @return */ public static ExceptionalStream iterate(final Throwables.BooleanSupplier hasNext, final Throwables.Supplier next) { N.checkArgNotNull(hasNext, "hasNext"); N.checkArgNotNull(next, "next"); return newStream(new ExceptionalIterator() { private boolean hasNextVal = false; @Override public boolean hasNext() throws E { if (hasNextVal == false) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() throws E { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } hasNextVal = false; return next.get(); } }); } /** * * @param * @param * @param init * @param hasNext * @param f * @return */ public static ExceptionalStream iterate(final T init, final Throwables.BooleanSupplier hasNext, final Throwables.UnaryOperator f) { N.checkArgNotNull(hasNext, "hasNext"); N.checkArgNotNull(f, "f"); return newStream(new ExceptionalIterator() { private final T NONE = (T) N.NULL_MASK; private T t = NONE; private boolean hasNextVal = false; @Override public boolean hasNext() throws E { if (hasNextVal == false) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() throws E { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } hasNextVal = false; return t = (t == NONE) ? init : f.apply(t); } }); } /** * * @param * @param * @param init * @param hasNext * @param f * @return */ public static ExceptionalStream iterate(final T init, final Throwables.Predicate hasNext, final Throwables.UnaryOperator f) { N.checkArgNotNull(hasNext, "hasNext"); N.checkArgNotNull(f, "f"); return newStream(new ExceptionalIterator() { private final T NONE = (T) N.NULL_MASK; private T t = NONE; private T cur = NONE; private boolean hasMore = true; private boolean hasNextVal = false; @Override public boolean hasNext() throws E { 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() throws E { if (hasNextVal == false && hasNext() == false) { throw new NoSuchElementException(); } t = cur; cur = NONE; hasNextVal = false; return t; } }); } /** * * @param * @param * @param init * @param f * @return */ public static ExceptionalStream iterate(final T init, final Throwables.UnaryOperator f) { N.checkArgNotNull(f, "f"); return newStream(new ExceptionalIterator() { private final T NONE = (T) N.NULL_MASK; private T t = NONE; @Override public boolean hasNext() throws E { return true; } @Override public T next() throws E { return t = t == NONE ? init : f.apply(t); } }); } public static ExceptionalStream generate(final Throwables.Supplier supplier) { N.checkArgNotNull(supplier, "supplier"); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { return true; } @Override public T next() throws E { return supplier.get(); } }); } public static ExceptionalStream repeat(final T element, final long n) { N.checkArgNotNegative(n, "n"); if (n == 0) { return empty(); } return newStream(new ExceptionalIterator() { private long cnt = n; @Override public boolean hasNext() throws E { return cnt > 0; } @Override public T next() throws E { if (cnt-- <= 0) { throw new NoSuchElementException(); } return element; } }); } public static ExceptionalStream range(final int startInclusive, final int endExclusive) { return range(startInclusive, endExclusive, 1); } public static ExceptionalStream range(final int startInclusive, final int endExclusive, final int by) { if (by == 0) { throw new IllegalArgumentException("'by' can't be zero"); } if (endExclusive == startInclusive || endExclusive > startInclusive != by > 0) { return empty(); } return newStream(new ExceptionalIterator() { private int next = startInclusive; private long cnt = (endExclusive * 1L - startInclusive) / by + ((endExclusive * 1L - startInclusive) % by == 0 ? 0 : 1); @Override public boolean hasNext() { return cnt > 0; } @Override public Integer next() { if (cnt-- <= 0) { throw new NoSuchElementException(); } int result = next; next += by; return result; } @Override public void advance(long n) { cnt = n >= cnt ? 0 : cnt - (int) n; next += n * by; } @Override public long count() { return cnt; } }); } public static ExceptionalStream rangeClosed(final int startInclusive, final int endInclusive) { return rangeClosed(startInclusive, endInclusive, 1); } public static ExceptionalStream rangeClosed(final int startInclusive, final int endInclusive, final int by) { if (by == 0) { throw new IllegalArgumentException("'by' can't be zero"); } if (endInclusive == startInclusive) { return of(startInclusive); } else if (endInclusive > startInclusive != by > 0) { return empty(); } return newStream(new ExceptionalIterator() { private int next = startInclusive; private long cnt = (endInclusive * 1L - startInclusive) / by + 1; @Override public boolean hasNext() { return cnt > 0; } @Override public Integer next() { if (cnt-- <= 0) { throw new NoSuchElementException(); } int result = next; next += by; return result; } @Override public void advance(long n) { cnt = n >= cnt ? 0 : cnt - (int) n; next += n * by; } @Override public long count() { return cnt; } }); } /** * * @param file * @return */ public static ExceptionalStream lines(final File file) { return lines(file, Charsets.UTF_8); } /** * * @param file * @param charset * @return */ public static ExceptionalStream lines(final File file, final Charset charset) { N.checkArgNotNull(file, "file"); final ExceptionalIterator iter = createLazyLineIterator(file, null, charset, null, true); return newStream(iter).onClose(new Throwables.Runnable() { @Override public void run() throws IOException { iter.close(); } }); } /** * * @param path * @return */ public static ExceptionalStream lines(final Path path) { return lines(path, Charsets.UTF_8); } /** * * @param path * @param charset * @return */ public static ExceptionalStream lines(final Path path, final Charset charset) { N.checkArgNotNull(path, "path"); final ExceptionalIterator iter = createLazyLineIterator(null, path, charset, null, true); return newStream(iter).onClose(new Throwables.Runnable() { @Override public void run() throws IOException { iter.close(); } }); } /** * * @param reader * @return */ public static ExceptionalStream lines(final Reader reader) { N.checkArgNotNull(reader, "reader"); return newStream(createLazyLineIterator(null, null, Charsets.UTF_8, reader, false)); } public static ExceptionalStream listFiles(final File parentPath) { if (!parentPath.exists()) { return empty(); } return of(parentPath.listFiles()); } public static ExceptionalStream listFiles(final File parentPath, final boolean recursively) { if (!parentPath.exists()) { return empty(); } else if (recursively == false) { return of(parentPath.listFiles()); } final ExceptionalIterator iter = new ExceptionalIterator() { 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 newStream(iter); } /** * Creates the lazy line iterator. * * @param file * @param path * @param charset * @param reader * @param closeReader * @return */ private static ExceptionalIterator createLazyLineIterator(final File file, final Path path, final Charset charset, final Reader reader, final boolean closeReader) { return ExceptionalIterator.of(new Throwables.Supplier, IOException>() { private ExceptionalIterator lazyIter = null; @Override public synchronized ExceptionalIterator get() { if (lazyIter == null) { lazyIter = new ExceptionalIterator() { 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 String cachedLine; private boolean finished = false; @Override public boolean hasNext() throws IOException { if (this.cachedLine != null) { return true; } else if (this.finished) { return false; } else { this.cachedLine = this.bufferedReader.readLine(); if (this.cachedLine == null) { this.finished = true; return false; } else { return true; } } } @Override public String next() throws IOException { if (!this.hasNext()) { throw new NoSuchElementException("No more lines"); } else { String res = this.cachedLine; this.cachedLine = null; return res; } } @Override public void close() throws IOException { if (closeReader) { IOUtil.close(bufferedReader); } } }; } return lazyIter; } }); } @SafeVarargs public static ExceptionalStream concat(final T[]... a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(Iterators.concat(a)); } @SafeVarargs public static ExceptionalStream concat(final Collection... a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(Iterators.concat(a)); } /** * * @param * @param * @param a * @return */ @SafeVarargs public static ExceptionalStream concat(final ExceptionalStream... a) { if (N.isNullOrEmpty(a)) { return empty(); } return concat(Array.asList(a)); } /** * * @param * @param * @param c * @return */ public static ExceptionalStream concat(final Collection> c) { if (N.isNullOrEmpty(c)) { return empty(); } return newStream(new ExceptionalIterator() { private final Iterator> iterators = c.iterator(); private ExceptionalStream cur; private ExceptionalIterator iter; @Override public boolean hasNext() throws E { while ((iter == null || iter.hasNext() == false) && iterators.hasNext()) { if (cur != null) { cur.close(); } cur = iterators.next(); iter = cur == null ? null : cur.elements; } return iter != null && iter.hasNext(); } @Override public T next() throws E { if ((iter == null || iter.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return iter.next(); } }, mergeCloseHandlers(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 ExceptionalStream zip(final A[] a, final B[] b, final Throwables.BiFunction zipFunction) { return zip(ObjIterator.of(a), ObjIterator.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 ExceptionalStream zip(final A[] a, final B[] b, final C[] c, final Throwables.TriFunction zipFunction) { return zip(ObjIterator.of(a), ObjIterator.of(b), ObjIterator.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 ExceptionalStream zip(final Collection a, final Collection b, final Throwables.BiFunction zipFunction) { return zip(N.iterate(a), N.iterate(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 ExceptionalStream zip(final Collection a, final Collection b, final Collection c, final Throwables.TriFunction zipFunction) { return zip(N.iterate(a), N.iterate(b), N.iterate(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 ExceptionalStream zip(final Iterator a, final Iterator b, final Throwables.BiFunction zipFunction) { return newStream(new ExceptionalIterator() { private final Iterator iterA = a == null ? ObjIterator. empty() : a; private final Iterator iterB = b == null ? ObjIterator. empty() : b; @Override public boolean hasNext() throws E { return iterA.hasNext() && iterB.hasNext(); } @Override public T next() throws E { return zipFunction.apply(iterA.next(), iterB.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 ExceptionalStream zip(final Iterator a, final Iterator b, final Iterator c, final Throwables.TriFunction zipFunction) { return newStream(new ExceptionalIterator() { private final Iterator iterA = a == null ? ObjIterator. empty() : a; private final Iterator iterB = b == null ? ObjIterator. empty() : b; private final Iterator iterC = c == null ? ObjIterator. empty() : c; @Override public boolean hasNext() throws E { return iterA.hasNext() && iterB.hasNext() && iterC.hasNext(); } @Override public T next() throws E { return zipFunction.apply(iterA.next(), iterB.next(), iterC.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 ExceptionalStream zip(final ExceptionalStream a, final ExceptionalStream b, final Throwables.BiFunction zipFunction) { return newStream(new ExceptionalIterator() { private final ExceptionalIterator iterA = iterate(a); private final ExceptionalIterator iterB = iterate(b); @Override public boolean hasNext() throws E { return iterA.hasNext() && iterB.hasNext(); } @Override public T next() throws E { return zipFunction.apply(iterA.next(), iterB.next()); } }, mergeCloseHandlers(Array.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 * @param c * @return */ public static ExceptionalStream zip(final ExceptionalStream a, final ExceptionalStream b, final ExceptionalStream c, final Throwables.TriFunction zipFunction) { return newStream(new ExceptionalIterator() { private final ExceptionalIterator iterA = iterate(a); private final ExceptionalIterator iterB = iterate(b); private final ExceptionalIterator iterC = iterate(c); @Override public boolean hasNext() throws E { return iterA.hasNext() && iterB.hasNext() && iterC.hasNext(); } @Override public T next() throws E { return zipFunction.apply(iterA.next(), iterB.next(), iterC.next()); } }, mergeCloseHandlers(Array.asList(a, b, 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 ExceptionalStream zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return zip(ObjIterator.of(a), ObjIterator.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 ExceptionalStream zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return zip(ObjIterator.of(a), ObjIterator.of(b), ObjIterator.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 ExceptionalStream zip(final Collection a, final Collection b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return zip(N.iterate(a), N.iterate(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 ExceptionalStream zip(final Collection a, final Collection b, final Collection c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return zip(N.iterate(a), N.iterate(b), N.iterate(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 ExceptionalStream zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return newStream(new ExceptionalIterator() { private final Iterator iterA = a == null ? ObjIterator. empty() : a; private final Iterator iterB = b == null ? ObjIterator. empty() : b; @Override public boolean hasNext() throws E { return iterA.hasNext() || iterB.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.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 ExceptionalStream zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return newStream(new ExceptionalIterator() { private final Iterator iterA = a == null ? ObjIterator. empty() : a; private final Iterator iterB = b == null ? ObjIterator. empty() : b; private final Iterator iterC = c == null ? ObjIterator. empty() : c; @Override public boolean hasNext() throws E { return iterA.hasNext() || iterB.hasNext() || iterC.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC); } }); } /** * 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 ExceptionalStream zip(final ExceptionalStream a, final ExceptionalStream b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return newStream(new ExceptionalIterator() { private final ExceptionalIterator iterA = iterate(a); private final ExceptionalIterator iterB = iterate(b); @Override public boolean hasNext() throws E { return iterA.hasNext() || iterB.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB); } }, mergeCloseHandlers(Array.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 * @param c * @return */ public static ExceptionalStream zip(final ExceptionalStream a, final ExceptionalStream b, final ExceptionalStream c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return newStream(new ExceptionalIterator() { private final ExceptionalIterator iterA = iterate(a); private final ExceptionalIterator iterB = iterate(b); private final ExceptionalIterator iterC = iterate(c); @Override public boolean hasNext() throws E { return iterA.hasNext() || iterB.hasNext() || iterC.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC); } }, mergeCloseHandlers(Array.asList(a, b, c))); } private static Deque> mergeCloseHandlers( Collection> closeHandlersList) { if (N.isNullOrEmpty(closeHandlersList)) { return null; } int count = 0; for (ExceptionalStream s : closeHandlersList) { count += N.size(s.closeHandlers); } if (count == 0) { return null; } final Deque> newCloseHandlers = new ArrayDeque<>(count); for (ExceptionalStream s : closeHandlersList) { if (N.notNullOrEmpty(s.closeHandlers)) { newCloseHandlers.addAll(s.closeHandlers); } } return newCloseHandlers; } /** * * @param a * @param b * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static ExceptionalStream merge(final T[] a, final T[] b, final Throwables.BiFunction nextSelector) { if (N.isNullOrEmpty(a)) { return of(b); } else if (N.isNullOrEmpty(b)) { return of(a); } return newStream(new ExceptionalIterator() { 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() throws E { if (cursorA < lenA) { if (cursorB < lenB) { if (nextSelector.apply(a[cursorA], b[cursorB]) == MergeResult.TAKE_FIRST) { return a[cursorA++]; } else { return b[cursorB++]; } } else { return a[cursorA++]; } } else if (cursorB < lenB) { return b[cursorB++]; } else { throw new NoSuchElementException(); } } }); } /** * * @param a * @param b * @param c * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ public static ExceptionalStream merge(final T[] a, final T[] b, final T[] c, final Throwables.BiFunction nextSelector) { return merge(merge(a, b, nextSelector).iteratorEx(), ExceptionalIterator. wrap(N.iterate(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 ExceptionalStream merge(final Collection a, final Collection b, final Throwables.BiFunction nextSelector) { return merge(N.iterate(a), N.iterate(b), 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 ExceptionalStream merge(final Collection a, final Collection b, final Collection c, final Throwables.BiFunction nextSelector) { return merge(N.iterate(a), N.iterate(b), N.iterate(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 ExceptionalStream merge(final Iterator a, final Iterator b, final Throwables.BiFunction nextSelector) { return merge(ExceptionalIterator. wrap(a), ExceptionalIterator. wrap(b), 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 ExceptionalStream merge(final Iterator a, final Iterator b, final Iterator c, final Throwables.BiFunction nextSelector) { return merge(merge(a, b, nextSelector).iteratorEx(), ExceptionalIterator. wrap(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 ExceptionalStream merge(final ExceptionalStream a, final ExceptionalStream b, final Throwables.BiFunction nextSelector) { return merge(iterate(a), iterate(b), nextSelector).onClose(new Throwables.Runnable() { @Override public void run() throws E { try { if (a != null) { a.close(); } } finally { if (b != null) { b.close(); } } } }); } public static ExceptionalStream merge(final ExceptionalStream a, final ExceptionalStream b, final ExceptionalStream c, final Throwables.BiFunction nextSelector) { return merge(merge(a, b, nextSelector), c, nextSelector); } static ExceptionalStream merge(final ExceptionalIterator a, final ExceptionalIterator b, final Throwables.BiFunction nextSelector) { return newStream(new ExceptionalIterator() { private final ExceptionalIterator iterA = a == null ? ExceptionalIterator.EMPTY : (ExceptionalIterator) a; private final ExceptionalIterator iterB = b == null ? ExceptionalIterator.EMPTY : (ExceptionalIterator) b; private T nextA = null; private T nextB = null; private boolean hasNextA = false; private boolean hasNextB = false; @Override public boolean hasNext() throws E { return hasNextA || hasNextB || iterA.hasNext() || iterB.hasNext(); } @Override public T next() throws E { if (hasNextA) { if (iterB.hasNext()) { if (nextSelector.apply(nextA, (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextA = false; hasNextB = true; return nextA; } else { return nextB; } } else { hasNextA = false; return nextA; } } else if (hasNextB) { if (iterA.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), nextB) == MergeResult.TAKE_FIRST) { return nextA; } else { hasNextA = true; hasNextB = false; return nextB; } } else { hasNextB = false; return nextB; } } else if (iterA.hasNext()) { if (iterB.hasNext()) { if (nextSelector.apply((nextA = iterA.next()), (nextB = iterB.next())) == MergeResult.TAKE_FIRST) { hasNextB = true; return nextA; } else { hasNextA = true; return nextB; } } else { return iterA.next(); } } else if (iterB.hasNext()) { return iterB.next(); } else { throw new NoSuchElementException(); } } }); } /** * * @param predicate * @return */ @IntermediateOp public ExceptionalStream filter(final Throwables.Predicate predicate) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { if (hasNext == false) { while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { hasNext = true; break; } } } return hasNext; } @Override public T next() throws E { if (hasNext == false && hasNext() == false) { throw new NoSuchElementException(); } hasNext = false; return next; } }, sorted, cmp, closeHandlers); } /** * * @param predicate * @param actionOnDroppedItem * @return */ @IntermediateOp public ExceptionalStream filter(final Throwables.Predicate predicate, final Throwables.Consumer actionOnDroppedItem) { assertNotClosed(); return filter(new Throwables.Predicate() { @Override public boolean test(T value) throws E { if (!predicate.test(value)) { actionOnDroppedItem.accept(value); return false; } return true; } }); } /** * * @param predicate * @return */ @IntermediateOp public ExceptionalStream takeWhile(final Throwables.Predicate predicate) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasMore = true; private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { if (hasNext == false && hasMore && elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { hasNext = true; } else { hasMore = false; } } return hasNext; } @Override public T next() throws E { if (hasNext == false && hasNext() == false) { throw new NoSuchElementException(); } hasNext = false; return next; } }, sorted, cmp, closeHandlers); } /** * * @param predicate * @return */ @IntermediateOp public ExceptionalStream dropWhile(final Throwables.Predicate predicate) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; private boolean dropped = false; @Override public boolean hasNext() throws E { if (hasNext == false) { if (dropped == false) { dropped = true; while (elements.hasNext()) { next = elements.next(); if (predicate.test(next) == false) { hasNext = true; break; } } } else if (elements.hasNext()) { next = elements.next(); hasNext = true; } } return hasNext; } @Override public T next() throws E { if (hasNext == false && hasNext() == false) { throw new NoSuchElementException(); } hasNext = false; return next; } }, sorted, cmp, closeHandlers); } /** * * @param predicate * @param actionOnDroppedItem * @return */ @IntermediateOp public ExceptionalStream dropWhile(final Throwables.Predicate predicate, final Throwables.Consumer actionOnDroppedItem) { assertNotClosed(); return filter(new Throwables.Predicate() { @Override public boolean test(T value) throws E { if (!predicate.test(value)) { actionOnDroppedItem.accept(value); return false; } return true; } }); } /** * * @param predicate * @return */ @IntermediateOp @Beta public ExceptionalStream skipUntil(final Throwables.Predicate predicate) { return dropWhile(Fnn.not(predicate)); } /** * Distinct and filter by occurrences. * * @return */ @IntermediateOp public ExceptionalStream distinct() { assertNotClosed(); final Set set = N.newHashSet(); return filter(new Throwables.Predicate() { @Override public boolean test(T value) { return set.add(hashKey(value)); } }); } /** * Distinct by the value mapped from keyMapper . * * @param keyMapper don't change value of the input parameter. * @return */ @IntermediateOp public ExceptionalStream distinctBy(final Throwables.Function keyMapper) { assertNotClosed(); final Set set = N.newHashSet(); return filter(new Throwables.Predicate() { @Override public boolean test(T value) throws E { return set.add(hashKey(keyMapper.apply(value))); } }); } /** * Distinct and filter by occurrences. * * @param keyMapper * @param occurrencesFilter * @return * @see #groupBy(Function, Collector) */ @IntermediateOp @TerminalOpTriggered @SuppressWarnings("rawtypes") public ExceptionalStream distinctBy(final Throwables.Function keyMapper, final Throwables.Predicate occurrencesFilter) { assertNotClosed(); final Supplier, Long>> supplier = Suppliers., Long> ofLinkedHashMap(); final Throwables.Function, E> keyedMapper = new Throwables.Function, E>() { @Override public Keyed apply(T t) throws E { return Keyed.of(keyMapper.apply(t), t); } }; final Throwables.Predicate, Long>, ? extends E> predicate = new Throwables.Predicate, Long>, E>() { @Override public boolean test(Map.Entry, Long> e) throws E { return occurrencesFilter.test(e.getValue()); } }; return groupBy(keyedMapper, Collectors.counting(), supplier).filter(predicate) .map((Throwables.Function, Long>, T, E>) (Throwables.Function) KK); } /** * Distinct and filter by occurrences. * * @param keyMapper * @param occurrencesFilter * @return * @see #groupBy(Function, Function, BinaryOperator) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream distinctBy(final Throwables.Function keyMapper, final Throwables.BinaryOperator mergeFunction) { assertNotClosed(); final Supplier> supplier = Suppliers. ofLinkedHashMap(); return groupBy(keyMapper, Fnn. identity(), mergeFunction, supplier).map(Fnn. value()); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream map(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public U next() throws E { return mapper.apply(elements.next()); } }, closeHandlers); } @IntermediateOp public ExceptionalStream mapFirst(final Throwables.Function mapperForFirst) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean isFirst = true; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public T next() throws E { if (isFirst) { isFirst = false; return mapperForFirst.apply(elements.next()); } else { return elements.next(); } } }, closeHandlers); } @IntermediateOp public ExceptionalStream mapFirstOrElse(final Throwables.Function mapperForFirst, final Throwables.Function mapperForElse) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean isFirst = true; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public R next() throws E { if (isFirst) { isFirst = false; return mapperForFirst.apply(elements.next()); } else { return mapperForElse.apply(elements.next()); } } }, closeHandlers); } @IntermediateOp public ExceptionalStream mapLast(final Throwables.Function mapperForLast) { assertNotClosed(); return newStream(new ExceptionalIterator() { private T next = null; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public T next() throws E { next = elements.next(); if (elements.hasNext()) { return next; } else { return mapperForLast.apply(next); } } }, closeHandlers); } @IntermediateOp public ExceptionalStream mapLastOrElse(final Throwables.Function mapperForLast, final Throwables.Function mapperForElse) { assertNotClosed(); return newStream(new ExceptionalIterator() { private T next = null; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public R next() throws E { next = elements.next(); if (elements.hasNext()) { return mapperForElse.apply(next); } else { return mapperForLast.apply(next); } } }, closeHandlers); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param * @param mapper * @return */ @IntermediateOp @Beta public ExceptionalStream mapPartial(final Throwables.Function, E> mapper) { return map(mapper).filter(it -> it.isPresent()).map(it -> it.get()); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param * @param mapper * @return */ @IntermediateOp @Beta public ExceptionalStream mapPartialJdk(final Throwables.Function, E> mapper) { return map(mapper).filter(it -> it.isPresent()).map(it -> it.get()); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flatMap( final Throwables.Function, ? extends E> mapper) { assertNotClosed(); final ExceptionalIterator iter = new ExceptionalIterator() { private ExceptionalIterator cur = null; private ExceptionalStream s = null; private Deque> closeHandle = null; @Override public boolean hasNext() throws E { while (cur == null || cur.hasNext() == false) { if (elements.hasNext()) { if (closeHandle != null) { final Deque> tmp = closeHandle; closeHandle = null; ExceptionalStream.close(tmp); } s = mapper.apply(elements.next()); if (s == null) { cur = null; } else { if (N.notNullOrEmpty(s.closeHandlers)) { closeHandle = s.closeHandlers; } cur = s.elements; } } else { cur = null; break; } } return cur != null && cur.hasNext(); } @Override public R next() throws E { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } @Override public void close() throws E { if (closeHandle != null) { ExceptionalStream.close(closeHandle); } } }; final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); newCloseHandlers.add(new Throwables.Runnable() { @Override public void run() throws E { iter.close(); } }); if (N.notNullOrEmpty(closeHandlers)) { newCloseHandlers.addAll(closeHandlers); } return newStream(iter, newCloseHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flattMap(final Throwables.Function, ? extends E> mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private Iterator cur = null; private Collection c = null; @Override public boolean hasNext() throws E { while ((cur == null || cur.hasNext() == false) && elements.hasNext()) { c = mapper.apply(elements.next()); cur = N.isNullOrEmpty(c) ? null : c.iterator(); } return cur != null && cur.hasNext(); } @Override public R next() throws E { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } }, closeHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flatMapp(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private R[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public R next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * @implNote same as ====> *
     * skipNull().flattMap(mapper)
     * 
* * @param * @param mapper * @return */ @IntermediateOp @Beta public ExceptionalStream flattMapIfNotNull(final Throwables.Function, ? extends E> mapper) { return skipNull().flattMap(mapper); } /** * @implNote same as ====> *
     * skipNull().flattMap(mapper).skipNull().flattMap(mapper2)
     * 
* * @param * @param * @param mapper * @param mapper2 * @return */ @IntermediateOp @Beta public ExceptionalStream flattMapIfNotNull(final Throwables.Function, ? extends E> mapper, final Throwables.Function, ? extends E> mapper2) { return skipNull().flattMap(mapper).skipNull().flattMap(mapper2); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToBoolean(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Boolean next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToChar(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private char[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Character next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToByte(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private byte[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Byte next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToShort(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private short[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Short next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToInteger(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private int[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Integer next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToLong(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private long[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Long next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToFloat(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private float[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Float next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapToDouble(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private double[] cur = null; private int len = 0; private int idx = 0; @Override public boolean hasNext() throws E { while (idx >= len) { if (elements.hasNext()) { cur = mapper.apply(elements.next()); len = N.len(cur); idx = 0; } else { cur = null; break; } } return idx < len; } @Override public Double next() throws E { if (idx >= len && hasNext() == false) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } // /** // * // * @param mapper // * @return // */ // @IntermediateOp // public ExceptionalStream flattMapToInt(final Throwables.Function mapper) { // final Throwables.Function, E> mapper2 = new Throwables.Function, E>() { // @Override // public ExceptionalStream apply(T t) throws E { // return ExceptionalStream.of(mapper.apply(t)); // } // }; // // return flatMap(mapper2); // } // // /** // * // * @param mapper // * @return // */ // @IntermediateOp // public ExceptionalStream flattMapToLong(final Throwables.Function mapper) { // final Throwables.Function, E> mapper2 = new Throwables.Function, E>() { // @Override // public ExceptionalStream apply(T t) throws E { // return ExceptionalStream.of(mapper.apply(t)); // } // }; // // return flatMap(mapper2); // } // // /** // * // * @param mapper // * @return // */ // @IntermediateOp // public ExceptionalStream flattMapToDouble(final Throwables.Function mapper) { // final Throwables.Function, E> mapper2 = new Throwables.Function, E>() { // @Override // public ExceptionalStream apply(T t) throws E { // return ExceptionalStream.of(mapper.apply(t)); // } // }; // // return flatMap(mapper2); // } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream slidingMap(Throwables.BiFunction mapper) { return slidingMap(mapper, 1); } /** * * @param * @param mapper * @param increment * @return */ @IntermediateOp public ExceptionalStream slidingMap(Throwables.BiFunction mapper, int increment) { return slidingMap(mapper, increment, false); } /** * * @param * @param mapper * @param increment * @param ignoreNotPaired * @return */ @IntermediateOp public ExceptionalStream slidingMap(final Throwables.BiFunction mapper, final int increment, final boolean ignoreNotPaired) { assertNotClosed(); checkArgPositive(increment, "increment"); final int windowSize = 2; return newStream(new ExceptionalIterator() { @SuppressWarnings("unchecked") private final T NONE = (T) N.NULL_MASK; private T prev = NONE; private T _1 = NONE; @Override public boolean hasNext() throws E { if (increment > windowSize && prev != NONE) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } prev = NONE; } if (ignoreNotPaired && _1 == NONE && elements.hasNext()) { _1 = elements.next(); } return elements.hasNext(); } @Override public R next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } if (ignoreNotPaired) { final R res = mapper.apply(_1, (prev = elements.next())); _1 = increment == 1 ? prev : NONE; return res; } else { if (increment == 1) { return mapper.apply(prev == NONE ? elements.next() : prev, (prev = (elements.hasNext() ? elements.next() : null))); } else { return mapper.apply(elements.next(), (prev = (elements.hasNext() ? elements.next() : null))); } } } }, closeHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream slidingMap(Throwables.TriFunction mapper) { return slidingMap(mapper, 1); } /** * * @param * @param mapper * @param increment * @return */ @IntermediateOp public ExceptionalStream slidingMap(Throwables.TriFunction mapper, int increment) { return slidingMap(mapper, increment, false); } /** * * @param * @param mapper * @param increment * @param ignoreNotPaired * @return */ @IntermediateOp public ExceptionalStream slidingMap(final Throwables.TriFunction mapper, final int increment, final boolean ignoreNotPaired) { assertNotClosed(); checkArgPositive(increment, "increment"); final int windowSize = 3; return newStream(new ExceptionalIterator() { @SuppressWarnings("unchecked") private final T NONE = (T) N.NULL_MASK; private T prev = NONE; private T prev2 = NONE; private T _1 = NONE; private T _2 = NONE; @Override public boolean hasNext() throws E { if (increment > windowSize && prev != NONE) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } prev = NONE; } if (ignoreNotPaired) { if (_1 == NONE && elements.hasNext()) { _1 = elements.next(); } if (_2 == NONE && elements.hasNext()) { _2 = elements.next(); } } return elements.hasNext(); } @Override public R next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } if (ignoreNotPaired) { final R res = mapper.apply(_1, _2, (prev = elements.next())); _1 = increment == 1 ? _2 : (increment == 2 ? prev : NONE); _2 = increment == 1 ? prev : NONE; return res; } else { if (increment == 1) { return mapper.apply(prev2 == NONE ? elements.next() : prev2, (prev2 = (prev == NONE ? (elements.hasNext() ? elements.next() : null) : prev)), (prev = (elements.hasNext() ? elements.next() : null))); } else if (increment == 2) { return mapper.apply(prev == NONE ? elements.next() : prev, elements.hasNext() ? elements.next() : null, (prev = (elements.hasNext() ? elements.next() : null))); } else { return mapper.apply(elements.next(), elements.hasNext() ? elements.next() : null, (prev = (elements.hasNext() ? elements.next() : null))); } } } }, closeHandlers); } /** * * @param the key type * @param keyMapper * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream>, E> groupBy(final Throwables.Function keyMapper) { return groupBy(keyMapper, Suppliers.> ofMap()); } /** * * @param the key type * @param keyMapper * @param mapFactory * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream>, E> groupBy(final Throwables.Function keyMapper, final Supplier>> mapFactory) { return groupBy(keyMapper, Fnn. identity(), mapFactory); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @return * @see Collectors#toMultimap(Function, Function) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream>, E> groupBy(Throwables.Function keyMapper, Throwables.Function valueMapper) { return groupBy(keyMapper, valueMapper, Suppliers.> ofMap()); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @param mapFactory * @return * @see Collectors#toMultimap(Function, Function, Supplier) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream>, E> groupBy(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Supplier>> mapFactory) { assertNotClosed(); return newStream(new ExceptionalIterator>, E>() { private Iterator>> iter = null; @Override public boolean hasNext() throws E { init(); return iter.hasNext(); } @Override public Map.Entry> next() throws E { init(); return iter.next(); } private void init() throws E { if (iter == null) { iter = ExceptionalStream.this.groupTo(keyMapper, valueMapper, mapFactory).entrySet().iterator(); } } }, closeHandlers); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @param mergeFunction * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Throwables.Function valueMapper, Throwables.BinaryOperator mergeFunction) { return groupBy(keyMapper, valueMapper, mergeFunction, Suppliers. ofMap()); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @param mergeFunction * @param mapFactory * @return * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Throwables.BinaryOperator mergeFunction, final Supplier> mapFactory) { assertNotClosed(); return newStream(new ExceptionalIterator, E>() { private Iterator> iter = null; @Override public boolean hasNext() throws E { init(); return iter.hasNext(); } @Override public Map.Entry next() throws E { init(); return iter.next(); } private void init() throws E { if (iter == null) { iter = ExceptionalStream.this.toMap(keyMapper, valueMapper, mergeFunction, mapFactory).entrySet().iterator(); } } }, closeHandlers); } /** * * @param the key type * @param * @param * @param keyMapper * @param downstream * @return * @throws E the e */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Collector downstream) { return groupBy(keyMapper, downstream, Suppliers. ofMap()); } /** * * @param the key type * @param * @param * @param keyMapper * @param downstream * @param mapFactory * @return * @throws E the e */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Collector downstream, final Supplier> mapFactory) { return groupBy(keyMapper, Fnn. identity(), downstream, mapFactory); } /** * * @param the key type * @param the value type * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @return * @throws E the e */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Collector downstream) { return groupBy(keyMapper, valueMapper, downstream, Suppliers. ofMap()); } /** * * @param the key type * @param the value type * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @param mapFactory * @return * @throws E the e */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> groupBy(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Collector downstream, final Supplier> mapFactory) { assertNotClosed(); return newStream(new ExceptionalIterator, E>() { private Iterator> iter = null; @Override public boolean hasNext() throws E { init(); return iter.hasNext(); } @Override public Map.Entry next() throws E { init(); return iter.next(); } private void init() throws E { if (iter == null) { iter = ExceptionalStream.this.toMap(keyMapper, valueMapper, downstream, mapFactory).entrySet().iterator(); } } }, closeHandlers); } /** * * @param predicate * @return * @see Collectors#partitioningBy(Predicate) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream>, E> partitionBy(final Throwables.Predicate predicate) { assertNotClosed(); return partitionBy(predicate, Collectors. toList()); } /** * * @param predicate * @param downstream * @return * @see Collectors#partitioningBy(Predicate, Collector) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> partitionBy(final Throwables.Predicate predicate, final Collector downstream) { assertNotClosed(); return newStream(new ExceptionalIterator, E>() { private Iterator> iter = null; @Override public boolean hasNext() throws E { init(); return iter.hasNext(); } @Override public Entry next() throws E { init(); return iter.next(); } private void init() throws E { if (iter == null) { iter = ExceptionalStream.this.partitionTo(predicate, downstream).entrySet().iterator(); } } }, closeHandlers); } /** * * @param * @param keyMapper * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream, E> countBy(final Throwables.Function keyMapper) { return groupBy(keyMapper, Collectors.countingInt()); } /** * * @param * @param collapsible * @param supplier * @return */ @IntermediateOp public > ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final Supplier supplier) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public C next() throws E { if (hasNext == false) { next = iter.next(); } final C c = supplier.get(); c.add(next); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { c.add(next); } else { break; } } return c; } }, closeHandlers); } /** * 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 runs sequentially, even in parallel stream. * * @param collapsible * @param mergeFunction * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final Throwables.BiFunction mergeFunction) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public T next() throws E { T res = hasNext ? next : (next = iter.next()); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { res = mergeFunction.apply(res, next); } else { break; } } return res; } }, closeHandlers); } /** * * @param * @param collapsible * @param init * @param op * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final U init, final Throwables.BiFunction op) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public U next() throws E { U res = op.apply(init, hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { res = op.apply(res, next); } else { break; } } return res; } }, closeHandlers); } /** * * @param * @param collapsible * @param supplier * @param accumulator * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final Throwables.Supplier supplier, final Throwables.BiConsumer accumulator) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public R next() throws E { final R container = supplier.get(); accumulator.accept(container, hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { accumulator.accept(container, next); } else { break; } } return container; } }, closeHandlers); } /** * * @param * @param
* @param collapsible * @param collector * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final Collector collector) { assertNotClosed(); final Supplier supplier = collector.supplier(); final BiConsumer accumulator = collector.accumulator(); final Function finisher = collector.finisher(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public R next() throws E { final A container = supplier.get(); accumulator.accept(container, hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { accumulator.accept(container, next); } else { break; } } return finisher.apply(container); } }, closeHandlers); } /** * * @param accumulator * @return */ @IntermediateOp public ExceptionalStream scan(final Throwables.BiFunction accumulator) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private T res = null; private boolean isFirst = true; @Override public boolean hasNext() throws E { return iter.hasNext(); } @Override public T next() throws E { if (isFirst) { isFirst = false; return (res = iter.next()); } else { return (res = accumulator.apply(res, iter.next())); } } }, closeHandlers); } /** * * @param * @param init * @param accumulator * @return */ @IntermediateOp public ExceptionalStream scan(final U init, final Throwables.BiFunction accumulator) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private U res = init; @Override public boolean hasNext() throws E { return iter.hasNext(); } @Override public U next() throws E { return (res = accumulator.apply(res, iter.next())); } }, closeHandlers); } /** * * @param * @param init * @param accumulator * @param initIncluded * @return */ @IntermediateOp public ExceptionalStream scan(final U init, final Throwables.BiFunction accumulator, final boolean initIncluded) { assertNotClosed(); if (initIncluded == false) { return scan(init, accumulator); } final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator() { private boolean isFirst = true; private U res = init; @Override public boolean hasNext() throws E { return isFirst || iter.hasNext(); } @Override public U next() throws E { if (isFirst) { isFirst = false; return init; } return (res = accumulator.apply(res, iter.next())); } }, closeHandlers); } /** * * @param c * @return * @see N#intersection(Collection, Collection) */ public ExceptionalStream intersection(final Collection c) { assertNotClosed(); final Multiset multiset = Multiset.from(c); return filter(new Throwables.Predicate() { @Override public boolean test(T value) { return multiset.getAndRemove(value) > 0; } }); } /** * * @param mapper * @param c * @return * @see N#intersection(Collection, Collection) */ public ExceptionalStream intersection(final Throwables.Function mapper, final Collection c) { assertNotClosed(); final Multiset multiset = Multiset.from(c); return filter(new Throwables.Predicate() { @Override public boolean test(T value) throws E { return multiset.getAndRemove(mapper.apply(value)) > 0; } }); } /** * * @param c * @return * @see N#difference(Collection, Collection) */ public ExceptionalStream difference(final Collection c) { assertNotClosed(); final Multiset multiset = Multiset.from(c); return filter(new Throwables.Predicate() { @Override public boolean test(T value) { return multiset.getAndRemove(value) < 1; } }); } /** * * @param mapper * @param c * @return * @see N#difference(Collection, Collection) */ public ExceptionalStream difference(final Function mapper, final Collection c) { assertNotClosed(); final Multiset multiset = Multiset.from(c); return filter(new Throwables.Predicate() { @Override public boolean test(T value) throws E { return multiset.getAndRemove(mapper.apply(value)) < 1; } }); } /** * * @param c * @return * @see N#symmetricDifference(Collection, Collection) */ public ExceptionalStream symmetricDifference(final Collection c) { assertNotClosed(); final Multiset multiset = Multiset.from(c); return filter(new Throwables.Predicate() { @Override public boolean test(T value) { return multiset.getAndRemove(value) < 1; } }).append(ExceptionalStream. of(c).filter(new Throwables.Predicate() { @Override public boolean test(T value) { return multiset.getAndRemove(value) > 0; } })); } /** * * @param defaultValue * @return * @see #appendIfEmpty(Object...) */ @IntermediateOp public final ExceptionalStream defaultIfEmpty(final T defaultValue) { return appendIfEmpty(defaultValue); } // /** // * // * @param defaultValues // * @return // * @see #appendIfEmpty(Object...) // */ // @IntermediateOp // public final ExceptionalStream defaultIfEmpty(final Collection defaultValues) { // return appendIfEmpty(defaultValues); // } /** * * @param supplier * @return * @see #appendIfEmpty(Throwables.Supplier) */ @IntermediateOp public final ExceptionalStream defaultIfEmpty(final Throwables.Supplier, ? extends E> supplier) { return appendIfEmpty(supplier); } @IntermediateOp @SafeVarargs public final ExceptionalStream prepend(final T... a) { return prepend(ExceptionalStream.of(a)); } @IntermediateOp public ExceptionalStream prepend(final Collection c) { return prepend(ExceptionalStream.of(c)); } /** * * @param s * @return */ @IntermediateOp public ExceptionalStream prepend(final ExceptionalStream s) { assertNotClosed(); return concat(s, this); } @IntermediateOp @SafeVarargs public final ExceptionalStream append(final T... a) { return append(ExceptionalStream.of(a)); } @IntermediateOp public ExceptionalStream append(final Collection c) { return append(ExceptionalStream.of(c)); } /** * * @param s * @return */ @IntermediateOp public ExceptionalStream append(final ExceptionalStream s) { assertNotClosed(); return concat(this, s); } @IntermediateOp @SafeVarargs public final ExceptionalStream appendIfEmpty(final T... a) { return appendIfEmpty(Arrays.asList(a)); } @IntermediateOp public ExceptionalStream appendIfEmpty(final Collection c) { assertNotClosed(); if (N.isNullOrEmpty(c)) { return newStream(elements, closeHandlers); } return newStream(new ExceptionalIterator() { private ExceptionalIterator iter; @Override public boolean hasNext() throws E { if (iter == null) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (iter == null) { init(); } return iter.next(); } @Override public void advance(long n) throws E { if (iter == null) { init(); } iter.advance(n); } @Override public long count() throws E { if (iter == null) { init(); } return iter.count(); } private void init() throws E { if (iter == null) { if (elements.hasNext()) { iter = elements; } else { iter = ExceptionalIterator.wrap(c.iterator()); } } } }, closeHandlers); } /** * Append if empty. * * @param supplier * @return * @throws E the e */ @IntermediateOp public ExceptionalStream appendIfEmpty(final Throwables.Supplier, ? extends E> supplier) { assertNotClosed(); final Holder> holder = new Holder<>(); return newStream(new ExceptionalIterator() { private ExceptionalIterator iter; @Override public boolean hasNext() throws E { if (iter == null) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (iter == null) { init(); } return iter.next(); } @Override public void advance(long n) throws E { if (iter == null) { init(); } iter.advance(n); } @Override public long count() throws E { if (iter == null) { init(); } return iter.count(); } private void init() throws E { if (iter == null) { if (elements.hasNext()) { iter = elements; } else { final ExceptionalStream s = supplier.get(); holder.setValue(s); iter = iterate(s); } } } }, closeHandlers).onClose(new Throwables.Runnable() { @Override public void run() throws E { close(holder); } }); } @IntermediateOp public ExceptionalStream throwIfEmpty(final Supplier exceptionSupplier) { this.checkArgNotNull(exceptionSupplier, "exceptionSupplier"); final Throwables.Supplier, E> tmp = new Throwables.Supplier, E>() { @Override public ExceptionalStream get() throws E { throw exceptionSupplier.get(); } }; return this.appendIfEmpty(tmp); } void close(Holder> holder) { if (holder.value() != null) { holder.value().close(); } } @TerminalOp public Optional applyIfNotEmpty(final Throwables.Function, R, E2> func) throws E, E2 { assertNotClosed(); try { if (elements.hasNext()) { return Optional.of(func.apply(this)); } else { return Optional.empty(); } } finally { close(); } } @TerminalOp public OrElse acceptIfNotEmpty(Throwables.Consumer, E2> action) throws E, E2 { assertNotClosed(); try { if (elements.hasNext()) { action.accept(this); return OrElse.TRUE; } } finally { close(); } return OrElse.FALSE; } /** * * @param action * @return */ @IntermediateOp public ExceptionalStream onEach(final Throwables.Consumer action) { assertNotClosed(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public T next() throws E { final T next = elements.next(); action.accept(next); return next; } }, sorted, cmp, closeHandlers); } /** * * @param action * @return */ @IntermediateOp public ExceptionalStream peek(final Throwables.Consumer action) { return onEach(action); } @IntermediateOp public ExceptionalStream peekFirst(final Throwables.Consumer action) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean isFirst = true; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public T next() throws E { if (isFirst) { isFirst = false; final T e = elements.next(); action.accept(e); return e; } else { return elements.next(); } } }, sorted, cmp, closeHandlers); } @IntermediateOp public ExceptionalStream peekLast(final Throwables.Consumer action) { assertNotClosed(); return newStream(new ExceptionalIterator() { private T next = null; @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public T next() throws E { next = elements.next(); if (elements.hasNext()) { return next; } else { final T e = elements.next(); action.accept(e); return e; } } }, sorted, cmp, closeHandlers); } /** * Returns ExceptionalStream of {@code List} with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). * * * @param chunkSize the desired size of each sub sequence (the last may be smaller). * @return */ @IntermediateOp public ExceptionalStream, E> splitToList(final int chunkSize) { return split(chunkSize, Factory. ofList()); } /** * Returns ExceptionalStream of {@code Set} with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). * * * @param chunkSize the desired size of each sub sequence (the last may be smaller). * @return */ @IntermediateOp public ExceptionalStream, E> splitToSet(final int chunkSize) { return split(chunkSize, Factory. ofSet()); } /** * Returns ExceptionalStream of {@code C} with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). * * * @param * @param chunkSize the desired size of each sub sequence (the last may be smaller). * @param collectionSupplier * @return */ @IntermediateOp public > ExceptionalStream split(final int chunkSize, final IntFunction collectionSupplier) { assertNotClosed(); checkArgPositive(chunkSize, "chunkSize"); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public C next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } final C result = collectionSupplier.apply(chunkSize); int cnt = 0; while (cnt++ < chunkSize && elements.hasNext()) { result.add(elements.next()); } return result; } @Override public long count() throws E { final long len = elements.count(); return len % chunkSize == 0 ? len / chunkSize : len / chunkSize + 1; } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); elements.advance(n > Long.MAX_VALUE / chunkSize ? Long.MAX_VALUE : n * chunkSize); } }, closeHandlers); } /** * * @param * @param * @param chunkSize the desired size of each sub sequence (the last may be smaller). * @param collector * @return */ @IntermediateOp public ExceptionalStream split(final int chunkSize, final Collector collector) { assertNotClosed(); checkArgPositive(chunkSize, "chunkSize"); final Supplier supplier = collector.supplier(); final BiConsumer accumulator = collector.accumulator(); final Function finisher = collector.finisher(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { return elements.hasNext(); } @Override public R next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } final A container = supplier.get(); int cnt = 0; while (cnt++ < chunkSize && elements.hasNext()) { accumulator.accept(container, elements.next()); } return finisher.apply(container); } @Override public long count() throws E { final long len = elements.count(); return len % chunkSize == 0 ? len / chunkSize : len / chunkSize + 1; } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); elements.advance(n > Long.MAX_VALUE / chunkSize ? Long.MAX_VALUE : n * chunkSize); } }, closeHandlers); } /** * Sliding to list. * * @param windowSize * @param increment * @return */ @IntermediateOp public ExceptionalStream, E> slidingToList(final int windowSize, final int increment) { return sliding(windowSize, increment, Factory. ofList()); } /** * Sliding to set. * * @param windowSize * @param increment * @return */ @IntermediateOp public ExceptionalStream, E> slidingToSet(final int windowSize, final int increment) { return sliding(windowSize, increment, Factory. ofSet()); } /** * * @param * @param windowSize * @param increment * @param collectionSupplier * @return */ @IntermediateOp public > ExceptionalStream sliding(final int windowSize, final int increment, final IntFunction collectionSupplier) { assertNotClosed(); checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment); return newStream(new ExceptionalIterator() { private Deque queue = null; private boolean toSkip = false; @Override public boolean hasNext() throws E { if (toSkip) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } toSkip = false; } return elements.hasNext(); } @Override public C next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } if (queue == null) { queue = new ArrayDeque<>(N.max(0, windowSize - increment)); } final C result = collectionSupplier.apply(windowSize); int cnt = 0; if (queue.size() > 0 && increment < windowSize) { cnt = queue.size(); for (T e : queue) { result.add(e); } if (queue.size() <= increment) { queue.clear(); } else { for (int i = 0; i < increment; i++) { queue.removeFirst(); } } } T next = null; while (cnt++ < windowSize && elements.hasNext()) { next = elements.next(); result.add(next); if (cnt > increment) { queue.add(next); } } toSkip = increment > windowSize; return result; } @Override public long count() throws E { final int prevSize = increment >= windowSize ? 0 : (queue == null ? 0 : queue.size()); final long len = prevSize + elements.count(); if (len == prevSize) { return 0; } else if (len <= windowSize) { return 1; } else { final long rlen = len - windowSize; return 1 + (rlen % increment == 0 ? rlen / increment : rlen / increment + 1); } } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); if (n == 0) { return; } if (increment >= windowSize) { elements.advance(n > Long.MAX_VALUE / increment ? Long.MAX_VALUE : n * increment); } else { if (N.isNullOrEmpty(queue)) { final long m = ((n - 1) > Long.MAX_VALUE / increment ? Long.MAX_VALUE : (n - 1) * increment); elements.advance(m); } else { final long m = (n > Long.MAX_VALUE / increment ? Long.MAX_VALUE : n * increment); final int prevSize = increment >= windowSize ? 0 : (queue == null ? 0 : queue.size()); if (m < prevSize) { for (int i = 0; i < m; i++) { queue.removeFirst(); } } else { if (queue != null) { queue.clear(); } elements.advance(m - prevSize); } } if (queue == null) { queue = new ArrayDeque<>(windowSize); } int cnt = queue.size(); while (cnt++ < windowSize && elements.hasNext()) { queue.add(elements.next()); } } } }, closeHandlers); } /** * * @param * @param * @param windowSize * @param increment * @param collector * @return */ @IntermediateOp public ExceptionalStream sliding(final int windowSize, final int increment, final Collector collector) { assertNotClosed(); checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment); final Supplier supplier = collector.supplier(); final BiConsumer accumulator = collector.accumulator(); final Function finisher = collector.finisher(); return newStream(new ExceptionalIterator() { private Deque queue = null; private boolean toSkip = false; @Override public boolean hasNext() throws E { if (toSkip) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } toSkip = false; } return elements.hasNext(); } @Override public R next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } if (increment < windowSize && queue == null) { queue = new ArrayDeque<>(windowSize - increment); } final A container = supplier.get(); int cnt = 0; if (increment < windowSize && queue.size() > 0) { cnt = queue.size(); for (T e : queue) { accumulator.accept(container, e); } if (queue.size() <= increment) { queue.clear(); } else { for (int i = 0; i < increment; i++) { queue.removeFirst(); } } } T next = null; while (cnt++ < windowSize && elements.hasNext()) { next = elements.next(); accumulator.accept(container, next); if (cnt > increment) { queue.add(next); } } toSkip = increment > windowSize; return finisher.apply(container); } @Override public long count() throws E { final int prevSize = increment >= windowSize ? 0 : (queue == null ? 0 : queue.size()); final long len = prevSize + elements.count(); if (len == prevSize) { return 0; } else if (len <= windowSize) { return 1; } else { final long rlen = len - windowSize; return 1 + (rlen % increment == 0 ? rlen / increment : rlen / increment + 1); } } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); if (n == 0) { return; } if (increment >= windowSize) { elements.advance(n > Long.MAX_VALUE / increment ? Long.MAX_VALUE : n * increment); } else { if (N.isNullOrEmpty(queue)) { final long m = ((n - 1) > Long.MAX_VALUE / increment ? Long.MAX_VALUE : (n - 1) * increment); elements.advance(m); } else { final long m = (n > Long.MAX_VALUE / increment ? Long.MAX_VALUE : n * increment); final int prevSize = increment >= windowSize ? 0 : (queue == null ? 0 : queue.size()); if (m < prevSize) { for (int i = 0; i < m; i++) { queue.removeFirst(); } } else { if (queue != null) { queue.clear(); } elements.advance(m - prevSize); } } if (queue == null) { queue = new ArrayDeque<>(windowSize); } int cnt = queue.size(); while (cnt++ < windowSize && elements.hasNext()) { queue.add(elements.next()); } } } }, closeHandlers); } /** * * @param n * @return */ @IntermediateOp public ExceptionalStream skip(final long n) { assertNotClosed(); checkArgNotNegative(n, "n"); return newStream(new ExceptionalIterator() { private boolean skipped = false; @Override public boolean hasNext() throws E { if (skipped == false) { skipped = true; advance(n); } return elements.hasNext(); } @Override public T next() throws E { if (skipped == false) { skipped = true; advance(n); } return elements.next(); } }, sorted, cmp, closeHandlers); } @IntermediateOp public ExceptionalStream skipNull() { return filter(Fnn.notNull()); } /** * * @param maxSize * @return */ @IntermediateOp public ExceptionalStream limit(final long maxSize) { assertNotClosed(); checkArgNotNegative(maxSize, "maxSize"); return newStream(new ExceptionalIterator() { private long cnt = 0; @Override public boolean hasNext() throws E { return cnt < maxSize && elements.hasNext(); } @Override public T next() throws E { if (cnt >= maxSize) { throw new NoSuchElementException(); } cnt++; return elements.next(); } }, sorted, cmp, closeHandlers); } // /** // * // * @param from // * @param to // * @return // * @deprecated // */ // @Deprecated // public ExceptionalStream slice(final long from, final long to) { // checkArgNotNegative(from, "from"); // checkArgNotNegative(to, "to"); // checkArgument(to >= from, "'to' can't be less than `from`"); // // return from == 0 ? limit(to) : skip(from).limit(to - from); // } @IntermediateOp public ExceptionalStream top(int n) { assertNotClosed(); return top(n, Comparators.NATURAL_ORDER); } @IntermediateOp public ExceptionalStream top(final int n, final Comparator comparator) { assertNotClosed(); checkArgPositive(n, "n"); return newStream(new ExceptionalIterator() { private boolean initialized = false; private T[] aar = null; private int cursor = 0; private int to; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } return cursor < to; } @Override public T next() throws E { if (initialized == false) { init(); } if (cursor >= to) { throw new NoSuchElementException(); } return aar[cursor++]; } @Override public long count() throws E { if (initialized == false) { init(); } return to - cursor; } @Override public void advance(long n) throws E { if (initialized == false) { init(); } cursor = n < to - cursor ? cursor + (int) n : to; } // @Override // public A[] toArray(A[] b) throws E { // if (initialized == false) { // init(); // } // // b = b.length >= to - cursor ? b : (A[]) N.newArray(b.getClass().getComponentType(), to - cursor); // // N.copy(aar, cursor, b, 0, to - cursor); // // return b; // } private void init() throws E { if (initialized == false) { initialized = true; if (sorted && isSameComparator(comparator, cmp)) { final LinkedList queue = new LinkedList<>(); while (elements.hasNext()) { if (queue.size() >= n) { queue.poll(); } queue.offer(elements.next()); } aar = (T[]) queue.toArray(); } else { final Queue heap = new PriorityQueue<>(n, comparator); T next = null; while (elements.hasNext()) { next = elements.next(); if (heap.size() >= n) { if (comparator.compare(next, heap.peek()) > 0) { heap.poll(); heap.offer(next); } } else { heap.offer(next); } } aar = (T[]) heap.toArray(); } to = aar.length; } } }, false, null, closeHandlers); } @IntermediateOp public ExceptionalStream last(final int n) { assertNotClosed(); checkArgNotNegative(n, "n"); if (n == 0) { return limit(0); } return newStream(new ExceptionalIterator() { private Iterator iter; private boolean initialized = false; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (initialized == false) { init(); } return iter.next(); } private void init() throws E { if (initialized == false) { initialized = true; final Deque deque = new ArrayDeque<>(Math.min(1024, n)); try { while (elements.hasNext()) { if (deque.size() >= n) { deque.pollFirst(); } deque.offerLast(elements.next()); } } finally { ExceptionalStream.this.close(); } iter = deque.iterator(); } } }, sorted, cmp, closeHandlers); } @IntermediateOp public ExceptionalStream skipLast(final int n) { assertNotClosed(); if (n <= 0) { return newStream(elements, sorted, cmp, closeHandlers); } return newStream(new ExceptionalIterator() { private Deque deque = null; @Override public boolean hasNext() throws E { if (deque == null) { deque = new ArrayDeque<>(Math.min(1024, n)); while (deque.size() < n && elements.hasNext()) { deque.offerLast(elements.next()); } } return elements.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } deque.offerLast(elements.next()); return deque.pollFirst(); } }, sorted, cmp, closeHandlers); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream reversed() { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean initialized = false; private T[] aar; private int cursor; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } return cursor > 0; } @Override public T next() throws E { if (initialized == false) { init(); } if (cursor <= 0) { throw new NoSuchElementException(); } return aar[--cursor]; } @Override public long count() throws E { if (initialized == false) { init(); } return cursor; } @Override public void advance(long n) throws E { if (initialized == false) { init(); } cursor = n < cursor ? cursor - (int) n : 0; } private void init() throws E { if (initialized == false) { initialized = true; aar = (T[]) ExceptionalStream.this.toArrayForIntermediateOp(); cursor = aar.length; } } }, false, null, closeHandlers); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream rotated(final int distance) { assertNotClosed(); if (distance == 0) { return newStream(elements, closeHandlers); } return newStream(new ExceptionalIterator() { private boolean initialized = false; private T[] aar; private int len; private int start; private int cnt = 0; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } return cnt < len; } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } return aar[(start + cnt++) % len]; } @Override public long count() throws E { if (initialized == false) { init(); } return len - cnt; } @Override public void advance(long n) throws E { if (initialized == false) { init(); } cnt = n < len - cnt ? cnt + (int) n : len; } private void init() throws E { if (initialized == false) { initialized = true; aar = (T[]) ExceptionalStream.this.toArrayForIntermediateOp(); len = aar.length; if (len > 0) { start = distance % len; if (start < 0) { start += len; } start = len - start; } } } }, false, null, closeHandlers); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream shuffled() { return shuffled(RAND); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream shuffled(final Random rnd) { assertNotClosed(); return lazyLoad(new Function() { @Override public Object[] apply(final Object[] a) { N.shuffle(a, rnd); return a; } }, false, null); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream sorted() { return sorted(Comparators.NATURAL_ORDER); } @IntermediateOp @TerminalOpTriggered public ExceptionalStream reverseSorted() { return sorted(Comparators.REVERSED_ORDER); } /** * * @param comparator * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream sorted(final Comparator comparator) { assertNotClosed(); final Comparator cmp = comparator == null ? Comparators.NATURAL_ORDER : comparator; if (sorted && cmp == this.cmp) { return newStream(elements, sorted, comparator, closeHandlers); } return lazyLoad(new Function() { @Override public Object[] apply(final Object[] a) { N.sort((T[]) a, cmp); return a; } }, true, cmp); } /** * * @param keyMapper * @return */ @IntermediateOp @TerminalOpTriggered @SuppressWarnings("rawtypes") public ExceptionalStream sortedBy(final Function keyMapper) { assertNotClosed(); final Comparator comparator = new Comparator() { @Override public int compare(T o1, T o2) { return N.compare(keyMapper.apply(o1), keyMapper.apply(o2)); } }; return sorted(comparator); } /** * * @param op * @param sorted * @param cmp * @return */ private ExceptionalStream lazyLoad(final Function op, final boolean sorted, final Comparator cmp) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean initialized = false; private T[] aar; private int cursor = 0; private int len; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } return cursor < len; } @Override public T next() throws E { if (initialized == false) { init(); } if (cursor >= len) { throw new NoSuchElementException(); } return aar[cursor++]; } @Override public long count() throws E { if (initialized == false) { init(); } return len - cursor; } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); if (initialized == false) { init(); } cursor = n > len - cursor ? len : cursor + (int) n; } private void init() throws E { if (initialized == false) { initialized = true; aar = (T[]) op.apply(ExceptionalStream.this.toArrayForIntermediateOp()); len = aar.length; } } }, sorted, cmp, closeHandlers); } @SequentialOnly @IntermediateOp public ExceptionalStream cycled() { assertNotClosed(); return newStream(new ExceptionalIterator() { private ExceptionalIterator iter = null; private List list = null; private T[] a = null; private int len = 0; private int cursor = -1; private T e = null; private boolean initialized = false; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } if (a == null && !iter.hasNext()) { a = (T[]) list.toArray(); len = a.length; cursor = 0; } return cursor < len || iter.hasNext(); } @Override public T next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } if (len > 0) { if (cursor >= len) { cursor = 0; } return a[cursor++]; } else { e = iter.next(); list.add(e); return e; } } private void init() { if (initialized == false) { initialized = true; iter = ExceptionalStream.this.iteratorEx(); list = new ArrayList<>(); } } }, false, null, closeHandlers); } @SequentialOnly @IntermediateOp public ExceptionalStream cycled(long times) { assertNotClosed(); return newStream(new ExceptionalIterator() { private ExceptionalIterator iter = null; private List list = null; private T[] a = null; private int len = 0; private int cursor = -1; private T e = null; private long m = 0; private boolean initialized = false; @Override public boolean hasNext() throws E { if (initialized == false) { init(); } if (a == null && !iter.hasNext()) { a = (T[]) list.toArray(); len = a.length; cursor = 0; m = 1; } return m < times && (cursor < len || times - m > 1) && (len > 0 || iter.hasNext()); } @Override public T next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } if (len > 0) { if (cursor >= len) { cursor = 0; m++; } return a[cursor++]; } else { e = iter.next(); list.add(e); return e; } } private void init() { if (initialized == false) { initialized = true; iter = ExceptionalStream.this.iteratorEx(); list = new ArrayList<>(); } } }, false, null, closeHandlers); } @IntermediateOp public ExceptionalStream intersperse(final T delimiter) { assertNotClosed(); return newStream(new ExceptionalIterator() { private final ExceptionalIterator iter = iteratorEx(); private boolean toInsert = false; @Override public boolean hasNext() throws E { return iter.hasNext(); } @Override public T next() throws E { if (hasNext() == false) { throw new NoSuchElementException(); } if (toInsert) { toInsert = false; return delimiter; } else { final T res = iter.next(); toInsert = true; return res; } } }); } @Beta @IntermediateOp public ExceptionalStream, E> indexed() { assertNotClosed(); return map(new Throwables.Function, E>() { private final MutableLong idx = new MutableLong(0); @Override public Indexed apply(T t) { return Indexed.of(t, idx.getAndIncrement()); } }); } /** * * @param b * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ @IntermediateOp public ExceptionalStream mergeWith(final Collection b, final Throwables.BiFunction nextSelector) { assertNotClosed(); return mergeWith(ExceptionalStream.of(b), nextSelector); } /** * * @param b * @param nextSelector first parameter is selected if Nth.FIRST is returned, otherwise the second parameter is selected. * @return */ @IntermediateOp public ExceptionalStream mergeWith(final ExceptionalStream b, final Throwables.BiFunction nextSelector) { assertNotClosed(); return ExceptionalStream.merge(this, b, nextSelector); } /** * * @param * @param * @param b * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final Collection b, final Throwables.BiFunction zipFunction) { assertNotClosed(); return zip(this, ExceptionalStream.of(b), zipFunction); } /** * * @param * @param * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final Collection b, final T valueForNoneA, final T2 valueForNoneB, final Throwables.BiFunction zipFunction) { assertNotClosed(); return zip(this, ExceptionalStream.of(b), valueForNoneA, valueForNoneB, zipFunction); } /** * * @param * @param * @param b * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final ExceptionalStream b, final Throwables.BiFunction zipFunction) { assertNotClosed(); return zip(this, b, zipFunction); } /** * * @param * @param * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final ExceptionalStream b, final T valueForNoneA, final T2 valueForNoneB, final Throwables.BiFunction zipFunction) { assertNotClosed(); return zip(this, b, valueForNoneA, valueForNoneB, zipFunction); } /** * * @param * @param * @param * @param b * @param c * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final ExceptionalStream b, final ExceptionalStream c, final Throwables.TriFunction zipFunction) { assertNotClosed(); return zip(this, b, c, zipFunction); } /** * * @param * @param * @param * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final ExceptionalStream b, final ExceptionalStream c, final T valueForNoneA, final T2 valueForNoneB, final T3 valueForNoneC, final Throwables.TriFunction zipFunction) { assertNotClosed(); return zip(this, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @return */ @IntermediateOp public ExceptionalStream, E> crossJoin(final Collection b) { return crossJoin(b, Fnn. pair()); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param func * @return */ @IntermediateOp public ExceptionalStream crossJoin(final Collection b, final Throwables.BiFunction func) { assertNotClosed(); return flatMap(new Throwables.Function, E>() { @Override public ExceptionalStream apply(final T t) throws E { return ExceptionalStream. of(b).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.cronJoin(this, ...)} * @param func * @return */ @IntermediateOp public ExceptionalStream crossJoin(final ExceptionalStream b, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); return flatMap(new Throwables.Function, E>() { private Collection c = null; @Override public ExceptionalStream apply(final T t) throws E { if (c == null) { c = b.toList(); } return ExceptionalStream. of(c).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @return */ @IntermediateOp public ExceptionalStream, E> innerJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) { return innerJoin(b, leftKeyMapper, rightKeyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream innerJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = ListMultimap.from(b, rightKeyMapper); } return ExceptionalStream. of(rightKeyMap.get(leftKeyMapper.apply(t))).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param keyMapper * @return */ public ExceptionalStream, E> innerJoin(final Collection b, final Throwables.Function keyMapper) { return innerJoin(b, keyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param keyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream innerJoin(final Collection b, final Throwables.Function keyMapper, final Throwables.BiFunction func) { return innerJoin(b, keyMapper, keyMapper, func); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.innerJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream innerJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = (ListMultimap) b.toMultimap(rightKeyMapper); } return ExceptionalStream. of(rightKeyMap.get(leftKeyMapper.apply(t))).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param predicate * @return * @deprecated The time complexity is O(n * m). You should try {@code innerJoin(Collection, Function, Function)} first. */ @Deprecated @SuppressWarnings("rawtypes") @IntermediateOp public ExceptionalStream, E> innerJoin(final Collection b, final Throwables.BiPredicate predicate) { return innerJoin(b, predicate, (Throwables.BiFunction) Fn.pair()); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param predicate * @param func * @return * @deprecated The time complexity is O(n * m). You should try {@code innerJoin(Collection, Function, Function, BiFunction)} first. */ @Deprecated @IntermediateOp public ExceptionalStream innerJoin(final Collection b, final Throwables.BiPredicate predicate, final Throwables.BiFunction func) { assertNotClosed(); return flatMap(new Throwables.Function, E>() { @Override public ExceptionalStream apply(final T t) { return ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(final U u) throws E { return predicate.test(t, u); } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @return */ @IntermediateOp public ExceptionalStream, E> fullJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) { return fullJoin(b, leftKeyMapper, rightKeyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream fullJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); final Map joinedRights = new IdentityHashMap<>(); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = ListMultimap.from(b, rightKeyMapper); } final List values = rightKeyMap.get(leftKeyMapper.apply(t)); return N.isNullOrEmpty(values) ? ExceptionalStream.of(func.apply(t, (U) null)) : ExceptionalStream. of(values).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }); } }).append(ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } @SuppressWarnings("rawtypes") private static Throwables.Function HOLDER_VALUE_GETTER = new Throwables.Function, Object, RuntimeException>() { @Override public Object apply(Holder t) { return t.value(); } }; /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param keyMapper * @return */ public ExceptionalStream, E> fullJoin(final Collection b, final Throwables.Function keyMapper) { return fullJoin(b, keyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param keyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream fullJoin(final Collection b, final Throwables.Function keyMapper, final Throwables.BiFunction func) { return fullJoin(b, keyMapper, keyMapper, func); } /** * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.fullJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream fullJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); final Map joinedRights = new IdentityHashMap<>(); final Holder> holder = new Holder<>(); return flatMap(new Throwables.Function, E>() { private List c = null; private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { c = (List) b.toList(); rightKeyMap = ListMultimap.from(c, rightKeyMapper); holder.setValue(c); } final List values = rightKeyMap.get(leftKeyMapper.apply(t)); return N.isNullOrEmpty(values) ? ExceptionalStream.of(func.apply(t, (U) null)) : ExceptionalStream. of(values).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }); } }).append(ExceptionalStream.>, E> of(holder) .flattMap((Throwables.Function>, List, E>) HOLDER_VALUE_GETTER) .filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }) .map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param predicate * @return * @deprecated The time complexity is O(n * m). You should try {@code fullJoin(Collection, Function, Function)} first. */ @Deprecated @SuppressWarnings("rawtypes") @IntermediateOp public ExceptionalStream, E> fullJoin(final Collection b, final Throwables.BiPredicate predicate) { return fullJoin(b, predicate, (Throwables.BiFunction) Fn.pair()); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param predicate * @param func * @return * @deprecated The time complexity is O(n * m). You should try {@code fullJoin(Collection, Function, Function, BiFunction)} first. */ @Deprecated @IntermediateOp public ExceptionalStream fullJoin(final Collection b, final Throwables.BiPredicate predicate, final Throwables.BiFunction func) { assertNotClosed(); final Map joinedRights = new IdentityHashMap<>(); return flatMap(new Throwables.Function, E>() { @Override public ExceptionalStream apply(final T t) { return ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(final U u) throws E { return predicate.test(t, u); } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }).appendIfEmpty(() -> ExceptionalStream. just(t).map(tt -> func.apply(t, (U) null))); } }).append(ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @return */ @IntermediateOp public ExceptionalStream, E> leftJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) { return leftJoin(b, leftKeyMapper, rightKeyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream leftJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = ListMultimap.from(b, rightKeyMapper); } final List values = rightKeyMap.get(leftKeyMapper.apply(t)); return N.isNullOrEmpty(values) ? ExceptionalStream. of(func.apply(t, (U) null)) : ExceptionalStream. of(values).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param keyMapper * @return */ public ExceptionalStream, E> leftJoin(final Collection b, final Throwables.Function keyMapper) { return leftJoin(b, keyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param keyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream leftJoin(final Collection b, final Throwables.Function keyMapper, final Throwables.BiFunction func) { return leftJoin(b, keyMapper, keyMapper, func); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.leftJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream leftJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = (ListMultimap) b.toMultimap(rightKeyMapper); } final List values = rightKeyMap.get(leftKeyMapper.apply(t)); return N.isNullOrEmpty(values) ? ExceptionalStream. of(func.apply(t, (U) null)) : ExceptionalStream. of(values).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }); } }); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param predicate * @return * @deprecated The time complexity is O(n * m). You should try {@code leftJoin(Collection, Function, Function)} first. */ @Deprecated @SuppressWarnings("rawtypes") @IntermediateOp public ExceptionalStream, E> leftJoin(final Collection b, final Throwables.BiPredicate predicate) { return leftJoin(b, predicate, (Throwables.BiFunction) Fn.pair()); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param predicate * @param func * @return * @deprecated The time complexity is O(n * m). You should try {@code leftJoin(Collection, Function, Function, BiFunction)} first. */ @Deprecated @IntermediateOp public ExceptionalStream leftJoin(final Collection b, final Throwables.BiPredicate predicate, final Throwables.BiFunction func) { assertNotClosed(); return flatMap(new Throwables.Function, E>() { @Override public ExceptionalStream apply(final T t) { return ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(final U u) throws E { return predicate.test(t, u); } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply(t, u); } }).appendIfEmpty(() -> ExceptionalStream. just(t).map(tt -> func.apply(t, (U) null))); } }); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @return */ @IntermediateOp public ExceptionalStream, E> rightJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) { return rightJoin(b, leftKeyMapper, rightKeyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream rightJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); final Map joinedRights = new IdentityHashMap<>(); return flatMap(new Throwables.Function, E>() { private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { rightKeyMap = ListMultimap.from(b, rightKeyMapper); } return ExceptionalStream. of(rightKeyMap.get(leftKeyMapper.apply(t))).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }); } }).append(ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param keyMapper * @return */ public ExceptionalStream, E> rightJoin(final Collection b, final Throwables.Function keyMapper) { return rightJoin(b, keyMapper, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param keyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream rightJoin(final Collection b, final Throwables.Function keyMapper, final Throwables.BiFunction func) { return rightJoin(b, keyMapper, keyMapper, func); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.rightJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream rightJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); final Map joinedRights = new IdentityHashMap<>(); final Holder> holder = new Holder<>(); return flatMap(new Throwables.Function, E>() { private List c = null; private ListMultimap rightKeyMap = null; @Override public ExceptionalStream apply(final T t) throws E { if (rightKeyMap == null) { c = (List) b.toList(); rightKeyMap = ListMultimap.from(c, rightKeyMapper); holder.setValue(c); } return ExceptionalStream. of(rightKeyMap.get(leftKeyMapper.apply(t))).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }); } }).append(ExceptionalStream.>, E> of(holder) .flattMap((Throwables.Function>, List, E>) HOLDER_VALUE_GETTER) .filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }) .map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param predicate * @return * @deprecated The time complexity is O(n * m). You should try {@code rightJoin(Collection, Function, Function)} first. */ @Deprecated @SuppressWarnings("rawtypes") @IntermediateOp public ExceptionalStream, E> rightJoin(final Collection b, final Throwables.BiPredicate predicate) { return rightJoin(b, predicate, (Throwables.BiFunction) Fn.pair()); } /** * The time complexity is O(n * m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param predicate * @param func * @return * @deprecated The time complexity is O(n * m). You should try {@code rightJoin(Collection, Function, Function, BiFunction)} first. */ @Deprecated @IntermediateOp public ExceptionalStream rightJoin(final Collection b, final Throwables.BiPredicate predicate, final Throwables.BiFunction func) { assertNotClosed(); final Map joinedRights = new IdentityHashMap<>(); return flatMap(new Throwables.Function, E>() { @Override public ExceptionalStream apply(final T t) { return ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(final U u) throws E { return predicate.test(t, u); } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { joinedRights.put(u, u); return func.apply(t, u); } }); } }).append(ExceptionalStream. of(b).filter(new Throwables.Predicate() { @Override public boolean test(U u) { return joinedRights.containsKey(u) == false; } }).map(new Throwables.Function() { @Override public R apply(U u) throws E { return func.apply((T) null, u); } })); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @return */ @IntermediateOp public ExceptionalStream>, E> groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper) { return groupJoin(b, leftKeyMapper, rightKeyMapper, Fnn., E> pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction, R, ? extends E> func) { assertNotClosed(); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map> map = null; private List val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, new ArrayList(0)); } else { return func.apply(t, val); } } private void init() throws E { if (initialized == false) { initialized = true; map = ExceptionalStream. of(b).groupTo(rightKeyMapper); } } }; return map(mapper); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param b * @param keyMapper * @return */ public ExceptionalStream>, E> groupJoin(final Collection b, final Throwables.Function keyMapper) { return groupJoin(b, keyMapper, Fnn., E> pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param keyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final Collection b, final Throwables.Function keyMapper, final Throwables.BiFunction, R, ? extends E> func) { return groupJoin(b, keyMapper, keyMapper, func); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.groupJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BiFunction, R, ? extends E> func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map> map = null; private List val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, new ArrayList(0)); } else { return func.apply(t, val); } } @SuppressWarnings("rawtypes") private void init() throws E { if (initialized == false) { initialized = true; map = (Map) b.groupTo(rightKeyMapper); } } }; return map(mapper); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param mergeFunction * @return */ @IntermediateOp public ExceptionalStream, E> groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BinaryOperator mergeFunction) { return groupJoin(b, leftKeyMapper, rightKeyMapper, mergeFunction, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param mergeFunction * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BinaryOperator mergeFunction, final Throwables.BiFunction func) { assertNotClosed(); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map map = null; private U val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, null); } else { return func.apply(t, val); } } private void init() throws E { if (initialized == false) { initialized = true; map = ExceptionalStream. of(b).toMap(rightKeyMapper, Fnn. identity(), mergeFunction); } } }; return map(mapper); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param b will be loaded to memory. If {@code b} is too big to load to memory, please use {@code b.groupJoin(this, ...)} * @param leftKeyMapper * @param rightKeyMapper * @param mergeFunction * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Throwables.BinaryOperator mergeFunction, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map map = null; private U val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, null); } else { return func.apply(t, val); } } private void init() throws E { if (initialized == false) { initialized = true; map = b.toMap(rightKeyMapper, Fnn. identity(), mergeFunction); } } }; return map(mapper); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param downstream * @return */ @IntermediateOp public ExceptionalStream, E> groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Collector downstream) { return groupJoin(b, leftKeyMapper, rightKeyMapper, downstream, Fnn. pair()); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param downstream * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final Collection b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Collector downstream, final Throwables.BiFunction func) { assertNotClosed(); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map map = null; private D val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, ExceptionalStream. empty().collect(downstream)); } else { return func.apply(t, val); } } private void init() throws E { if (initialized == false) { initialized = true; map = ExceptionalStream. of(b).toMap(rightKeyMapper, Fnn. identity(), downstream); } } }; return map(mapper); } /** * The time complexity is O(n + m) : n is the size of this Stream and m is the size of specified collection b. * * @param * @param * @param * @param * @param * @param b * @param leftKeyMapper * @param rightKeyMapper * @param downstream * @param func * @return */ @IntermediateOp public ExceptionalStream groupJoin(final ExceptionalStream b, final Throwables.Function leftKeyMapper, final Throwables.Function rightKeyMapper, final Collector downstream, final Throwables.BiFunction func) { assertNotClosed(); checkArgNotNull(b, "stream 'b' can not be null"); final Throwables.Function mapper = new Throwables.Function() { private volatile boolean initialized = false; private volatile Map map = null; private D val = null; @Override public R apply(T t) throws E { if (initialized == false) { init(); } val = map.get(leftKeyMapper.apply(t)); if (val == null) { return func.apply(t, ExceptionalStream. empty().collect(downstream)); } else { return func.apply(t, val); } } private void init() throws E { if (initialized == false) { initialized = true; map = b.toMap(rightKeyMapper, Fnn. identity(), downstream); } } }; return map(mapper); } /** * * @param * @param action * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEach(Throwables.Consumer action) throws E, E2 { assertNotClosed(); checkArgNotNull(action, "action"); try { while (elements.hasNext()) { action.accept(elements.next()); } } finally { close(); } } /** * * @param * @param action * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEachIndexed(Throwables.IndexedConsumer action) throws E, E2 { assertNotClosed(); checkArgNotNull(action, "action"); final MutableInt idx = MutableInt.of(0); try { while (elements.hasNext()) { action.accept(idx.getAndIncrement(), elements.next()); } } finally { close(); } } @TerminalOp @Beta public void forEachToBreak(final Throwables.BiConsumer action) throws E, E2 { assertNotClosed(); final MutableBoolean flagToBreak = MutableBoolean.of(false); final Throwables.Consumer tmp = new Throwables.Consumer() { @Override public void accept(T t) throws E2 { action.accept(t, flagToBreak); } }; takeWhile(new Throwables.Predicate() { @Override public boolean test(T value) { return flagToBreak.isFalse(); } }).forEach(tmp); } @TerminalOp @Beta public void forEachToBreak(final MutableBoolean flagToBreak, final Throwables.Consumer action) throws E, E2 { assertNotClosed(); takeWhile(new Throwables.Predicate() { @Override public boolean test(T value) { return flagToBreak.isFalse(); } }).forEach(action); } /** * * @param * @param * @param action * @param onComplete * @throws E the e * @throws E2 the e2 * @throws E3 the e3 */ @TerminalOp public void forEach(final Throwables.Consumer action, final Throwables.Runnable onComplete) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(action, "action"); checkArgNotNull(onComplete, "onComplete"); try { while (elements.hasNext()) { action.accept(elements.next()); } onComplete.run(); } finally { close(); } } /** * * @param * @param * @param * @param flatMapper * @param action * @throws E the e * @throws E2 the e2 * @throws E3 the e3 */ @TerminalOp public void forEach(final Throwables.Function, E2> flatMapper, final Throwables.BiConsumer action) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(flatMapper, "flatMapper"); checkArgNotNull(action, "action"); Collection c = null; T next = null; try { while (elements.hasNext()) { next = elements.next(); c = flatMapper.apply(next); if (N.notNullOrEmpty(c)) { for (U u : c) { action.accept(next, u); } } } } finally { close(); } } /** * * @param * @param * @param * @param * @param * @param flatMapper * @param flatMapper2 * @param action * @throws E the e * @throws E2 the e2 * @throws E3 the e3 * @throws E4 the e4 */ @TerminalOp public void forEach( final Throwables.Function, E2> flatMapper, final Throwables.Function, E3> flatMapper2, final Throwables.TriConsumer action) throws E, E2, E3, E4 { assertNotClosed(); checkArgNotNull(flatMapper, "flatMapper"); checkArgNotNull(flatMapper2, "flatMapper2"); checkArgNotNull(action, "action"); Collection c2 = null; Collection c3 = null; T next = null; try { while (elements.hasNext()) { next = elements.next(); c2 = flatMapper.apply(next); if (N.notNullOrEmpty(c2)) { for (T2 t2 : c2) { c3 = flatMapper2.apply(t2); if (N.notNullOrEmpty(c3)) { for (T3 t3 : c3) { action.accept(next, t2, t3); } } } } } } finally { close(); } } /** * For each pair. * * @param * @param action * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEachPair(final Throwables.BiConsumer action) throws E, E2 { forEachPair(action, 1); } /** * For each pair. * * @param * @param action * @param increment * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEachPair(final Throwables.BiConsumer action, final int increment) throws E, E2 { assertNotClosed(); final int windowSize = 2; checkArgPositive(increment, "increment"); try { boolean isFirst = true; T prev = null; while (elements.hasNext()) { if (increment > windowSize && isFirst == false) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } if (elements.hasNext() == false) { break; } } if (increment == 1) { action.accept(isFirst ? elements.next() : prev, (prev = (elements.hasNext() ? elements.next() : null))); } else { action.accept(elements.next(), elements.hasNext() ? elements.next() : null); } isFirst = false; } } finally { close(); } } /** * For each triple. * * @param * @param action * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEachTriple(final Throwables.TriConsumer action) throws E, E2 { forEachTriple(action, 1); } /** * For each triple. * * @param * @param action * @param increment * @throws E the e * @throws E2 the e2 */ @TerminalOp public void forEachTriple(final Throwables.TriConsumer action, final int increment) throws E, E2 { assertNotClosed(); final int windowSize = 3; checkArgPositive(increment, "increment"); try { boolean isFirst = true; T prev = null; T prev2 = null; while (elements.hasNext()) { if (increment > windowSize && isFirst == false) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } if (elements.hasNext() == false) { break; } } if (increment == 1) { action.accept(isFirst ? elements.next() : prev2, (prev2 = (isFirst ? (elements.hasNext() ? elements.next() : null) : prev)), (prev = (elements.hasNext() ? elements.next() : null))); } else if (increment == 2) { action.accept(isFirst ? elements.next() : prev, elements.hasNext() ? elements.next() : null, (prev = (elements.hasNext() ? elements.next() : null))); } else { action.accept(elements.next(), elements.hasNext() ? elements.next() : null, elements.hasNext() ? elements.next() : null); } isFirst = false; } } finally { close(); } } /** * * @param comparator * @return * @throws E the e */ @TerminalOp public Optional min(Comparator comparator) throws E { assertNotClosed(); try { if (elements.hasNext() == false) { return Optional.empty(); } else if (sorted && isSameComparator(comparator, comparator)) { return Optional.of(elements.next()); } comparator = comparator == null ? Comparators.NATURAL_ORDER : comparator; T candidate = elements.next(); T next = null; while (elements.hasNext()) { next = elements.next(); if (comparator.compare(next, candidate) < 0) { candidate = next; } } return Optional.of(candidate); } finally { close(); } } /** * * @param keyMapper * @return * @throws E the e */ @TerminalOp @SuppressWarnings("rawtypes") public Optional minBy(final Function keyMapper) throws E { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); try { final Comparator comparator = Fn.comparingBy(keyMapper); return min(comparator); } finally { close(); } } /** * * @param comparator * @return * @throws E the e */ @TerminalOp public Optional max(Comparator comparator) throws E { assertNotClosed(); try { if (elements.hasNext() == false) { return Optional.empty(); } else if (sorted && isSameComparator(comparator, comparator)) { T next = null; while (elements.hasNext()) { next = elements.next(); } return Optional.of(next); } comparator = comparator == null ? Comparators.NATURAL_ORDER : comparator; T candidate = elements.next(); T next = null; while (elements.hasNext()) { next = elements.next(); if (comparator.compare(next, candidate) > 0) { candidate = next; } } return Optional.of(candidate); } finally { close(); } } /** * * @param keyMapper * @return * @throws E the e */ @TerminalOp @SuppressWarnings("rawtypes") public Optional maxBy(final Function keyMapper) throws E { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); try { final Comparator comparator = Fn.comparingBy(keyMapper); return max(comparator); } finally { close(); } } /** * * @param * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public boolean anyMatch(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); try { while (elements.hasNext()) { if (predicate.test(elements.next())) { return true; } } return false; } finally { close(); } } /** * * @param * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public boolean allMatch(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); try { while (elements.hasNext()) { if (predicate.test(elements.next()) == false) { return false; } } return true; } finally { close(); } } /** * * @param * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public boolean noneMatch(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); try { while (elements.hasNext()) { if (predicate.test(elements.next())) { return false; } } return true; } finally { close(); } } /** * * @param * @param atLeast * @param atMost * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public boolean nMatch(final long atLeast, final long atMost, final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); checkArgNotNegative(atLeast, "atLeast"); checkArgNotNegative(atMost, "atMost"); checkArgument(atLeast <= atMost, "'atLeast' must be <= 'atMost'"); long cnt = 0; try { while (elements.hasNext()) { if (predicate.test(elements.next())) { if (++cnt > atMost) { return false; } } } } finally { close(); } return cnt >= atLeast && cnt <= atMost; } /** * * @param * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public Optional findFirst(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); try { T e = null; while (elements.hasNext()) { e = elements.next(); if (predicate.test(e)) { return Optional.of(e); } } } finally { close(); } return (Optional) Optional.empty(); } /** * Consider using: {@code stream.reversed().findFirst(predicate)} for better performance if possible. * * @param * @param predicate * @return * @throws E * @throws E2 */ @TerminalOp public Optional findLast(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); try { if (elements.hasNext() == false) { return (Optional) Optional.empty(); } boolean hasResult = false; T e = null; T result = null; while (elements.hasNext()) { e = elements.next(); if (predicate.test(e)) { result = e; hasResult = true; } } return hasResult ? Optional.of(result) : (Optional) Optional.empty(); } finally { close(); } } /** * Same as {@code findFirst(Throwables.Predicate)}. * * @param * @param predicate * @return * @throws E * @throws E2 * @see #findFirst(com.landawn.abacus.util.Throwables.Predicate) */ @TerminalOp public Optional findAny(final Throwables.Predicate predicate) throws E, E2 { return findFirst(predicate); } @TerminalOp @SafeVarargs public final boolean containsAll(final T... a) throws E { assertNotClosed(); try { if (N.isNullOrEmpty(a)) { return true; } else if (a.length == 1 || (a.length == 2 && N.equals(a[0], a[1]))) { return anyMatch(Fnn. pp(Fn. equal(a[0]))); } else if (a.length == 2) { return filter(new Throwables.Predicate() { private final T val1 = a[0]; private final T val2 = a[1]; @Override public boolean test(T t) { return N.equals(t, val1) || N.equals(t, val2); } }).distinct().limit(2).count() == 2; } else { return containsAll(N.asSet(a)); } } finally { close(); } } @TerminalOp public boolean containsAll(final Collection c) throws E { assertNotClosed(); try { if (N.isNullOrEmpty(c)) { return true; } else if (c.size() == 1) { final T val = c instanceof List ? ((List) c).get(0) : c.iterator().next(); return anyMatch(Fnn. pp(Fn. equal(val))); } else { final Set set = c instanceof Set ? (Set) c : N.newHashSet(c); final int distinctCount = set.size(); return filter(new Throwables.Predicate() { @Override public boolean test(T t) { return set.contains(t); } }).distinct().limit(distinctCount).count() == distinctCount; } } finally { close(); } } @TerminalOp @SafeVarargs public final boolean containsAny(final T... a) throws E { assertNotClosed(); try { if (N.isNullOrEmpty(a)) { return false; } else if (a.length == 1 || (a.length == 2 && N.equals(a[0], a[1]))) { return anyMatch(Fnn. pp(Fn. equal(a[0]))); } else if (a.length == 2) { return anyMatch(new Throwables.Predicate() { private final T val1 = a[0]; private final T val2 = a[1]; @Override public boolean test(T t) { return N.equals(t, val1) || N.equals(t, val2); } }); } else { final Set set = N.asSet(a); return anyMatch(new Throwables.Predicate() { @Override public boolean test(T t) { return set.contains(t); } }); } } finally { close(); } } @TerminalOp public boolean containsAny(final Collection c) throws E { assertNotClosed(); try { if (N.isNullOrEmpty(c)) { return false; } else if (c.size() == 1) { final T val = c instanceof List ? ((List) c).get(0) : c.iterator().next(); return anyMatch(Fnn. pp(Fn. equal(val))); } else { final Set set = c instanceof Set ? (Set) c : N.newHashSet(c); return anyMatch(new Throwables.Predicate() { @Override public boolean test(T t) { return set.contains(t); } }); } } finally { close(); } } @TerminalOp public boolean hasDuplicates() throws E { assertNotClosed(); try { final Set set = N.newHashSet(); while (elements.hasNext()) { if (set.add(elements.next()) == false) { return true; } } return false; } finally { close(); } } @TerminalOp public Optional kthLargest(int k, Comparator comparator) throws E { assertNotClosed(); checkArgPositive(k, "k"); try { if (elements.hasNext() == false) { return Optional.empty(); } else if (sorted && isSameComparator(comparator, this.cmp)) { final LinkedList queue = new LinkedList<>(); while (elements.hasNext()) { if (queue.size() >= k) { queue.poll(); } queue.offer(elements.next()); } return queue.size() < k ? (Optional) Optional.empty() : Optional.of(queue.peek()); } comparator = comparator == null ? Comparators.NATURAL_ORDER : comparator; final Queue queue = new PriorityQueue<>(k, comparator); T e = null; while (elements.hasNext()) { e = elements.next(); if (queue.size() < k) { queue.offer(e); } else { if (comparator.compare(e, queue.peek()) > 0) { queue.poll(); queue.offer(e); } } } return queue.size() < k ? (Optional) Optional.empty() : Optional.of(queue.peek()); } finally { close(); } } @TerminalOp public Optional> percentiles(Comparator comparator) throws E { assertNotClosed(); try { final Object[] a = sorted(comparator).toArray(); if (N.isNullOrEmpty(a)) { return Optional.empty(); } return Optional.of((Map) N.percentiles(a)); } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public Optional first() throws E { assertNotClosed(); try { if (elements.hasNext() == false) { return Optional.empty(); } return Optional.of(elements.next()); } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public Optional last() throws E { assertNotClosed(); try { if (elements.hasNext() == false) { return Optional.empty(); } T next = elements.next(); while (elements.hasNext()) { next = elements.next(); } return Optional.of(next); } finally { close(); } } /** * @param position in current stream(not upstream or origin source). It starts from 0. * @return * @throws E the e */ @TerminalOp @Beta public Optional elementAt(final long position) throws E { assertNotClosed(); checkArgNotNegative(position, "position"); if (position == 0) { return first(); } else { return skip(position).first(); } } /** * * @return * @throws DuplicatedResultException if there are more than one elements. * @throws E the e */ @TerminalOp public Optional onlyOne() throws DuplicatedResultException, E { assertNotClosed(); try { Optional result = Optional.empty(); if (elements.hasNext()) { result = Optional.of(elements.next()); if (elements.hasNext()) { throw new DuplicatedResultException("There are at least two elements: " + Strings.concat(result.get(), ", ", elements.next())); } } return result; } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public long count() throws E { assertNotClosed(); try { return elements.count(); } finally { close(); } } // It won't work for findFirst/only/anyMatch... // public Pair countAnd(final Throwables.Function, R, E> terminalAction) throws E { // checkArgNotNull(terminalAction, "terminalAction"); // // final MutableLong count = MutableLong.of(0); // // final Throwables.Consumer action = new Throwables.Consumer() { // @Override // public void accept(T t) { // count.incrementAndGet(); // } // }; // // final R r = terminalAction.apply(this.onEach(action)); // // return Pair.of(count.value(), r); // } /** * * @return * @throws E the e */ @TerminalOp public Object[] toArray() throws E { return toArray(true); } Object[] toArray(final boolean closeStream) throws E { assertNotClosed(); try { return toList().toArray(); } finally { if (closeStream) { close(); } } } Object[] toArrayForIntermediateOp() throws E { // return toArray(false); return toArray(true); } /** * * @param * @param generator * @return * @throws E the e */ @TerminalOp public A[] toArray(IntFunction generator) throws E { assertNotClosed(); checkArgNotNull(generator, "generator"); try { final List list = toList(); return list.toArray(generator.apply(list.size())); } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public List toList() throws E { assertNotClosed(); try { final List result = new ArrayList<>(); while (elements.hasNext()) { result.add(elements.next()); } return result; } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public Set toSet() throws E { assertNotClosed(); try { final Set result = N.newHashSet(); while (elements.hasNext()) { result.add(elements.next()); } return result; } finally { close(); } } /** * * @return * @throws E the e */ @TerminalOp public ImmutableList toImmutableList() throws E { return ImmutableList.of(toList()); } /** * * @return * @throws E the e */ @TerminalOp public ImmutableSet toImmutableSet() throws E { return ImmutableSet.of(toSet()); } /** * * @param * @param supplier * @return * @throws E the e */ @TerminalOp public > C toCollection(final Supplier supplier) throws E { assertNotClosed(); checkArgNotNull(supplier, "supplier"); try { final C result = supplier.get(); while (elements.hasNext()) { result.add(elements.next()); } return result; } finally { close(); } } @TerminalOp public R toListAndThen(Throwables.Function, R, E2> func) throws E, E2 { assertNotClosed(); return func.apply(toList()); } @TerminalOp public R toSetAndThen(Throwables.Function, R, E2> func) throws E, E2 { assertNotClosed(); return func.apply(toSet()); } @TerminalOp public , E2 extends Exception> R toCollectionAndThen(Supplier supplier, Throwables.Function func) throws E, E2 { assertNotClosed(); return func.apply(toCollection(supplier)); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @return * @throws E the e * @throws IllegalStateException if there are duplicated keys. * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @TerminalOp public Map toMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper) throws E, E2, E3, IllegalStateException { return toMap(keyMapper, valueMapper, Suppliers. ofMap()); } /** * * @param the key type * @param the value type * @param * @param keyMapper * @param valueMapper * @param mapFactory * @return * @throws E the e * @throws IllegalStateException if there are duplicated keys. * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @TerminalOp public , E2 extends Exception, E3 extends Exception> M toMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Supplier mapFactory) throws E, E2, E3, IllegalStateException { return toMap(keyMapper, valueMapper, Fnn. throwingMerger(), mapFactory); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @param mergeFunction * @return * @throws E the e * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @TerminalOp public Map toMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Throwables.BinaryOperator mergeFunction) throws E, E2, E3 { return toMap(keyMapper, valueMapper, mergeFunction, Suppliers. ofMap()); } /** * * @param the key type * @param the value type * @param * @param keyMapper * @param valueMapper * @param mergeFunction * @param mapFactory * @return * @throws E the e * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @TerminalOp public , E2 extends Exception, E3 extends Exception> M toMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Throwables.BinaryOperator mergeFunction, final Supplier mapFactory) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); checkArgNotNull(valueMapper, "valueMapper"); checkArgNotNull(mergeFunction, "mergeFunction"); checkArgNotNull(mapFactory, "mapFactory"); try { final M result = mapFactory.get(); T next = null; while (elements.hasNext()) { next = elements.next(); Maps.merge(result, keyMapper.apply(next), valueMapper.apply(next), mergeFunction); } return result; } finally { close(); } } /** * * @param the key type * @param * @param * @param keyMapper * @param downstream * @return * @throws E the e */ @TerminalOp public Map toMap(final Throwables.Function keyMapper, final Collector downstream) throws E, E2 { return toMap(keyMapper, downstream, Suppliers. ofMap()); } /** * * @param the key type * @param * @param * @param * @param keyMapper * @param downstream * @param mapFactory * @return * @throws E the e */ @TerminalOp public , E2 extends Exception> M toMap(final Throwables.Function keyMapper, final Collector downstream, final Supplier mapFactory) throws E, E2 { return toMap(keyMapper, Fnn. identity(), downstream, mapFactory); } /** * * @param the key type * @param the value type * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @return * @throws E the e */ @TerminalOp public Map toMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Collector downstream) throws E, E2, E3 { return toMap(keyMapper, valueMapper, downstream, Suppliers. ofMap()); } /** * * @param the key type * @param the value type * @param * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @param mapFactory * @return * @throws E the e */ @TerminalOp public , E2 extends Exception, E3 extends Exception> M toMap( final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Collector downstream, final Supplier mapFactory) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); checkArgNotNull(valueMapper, "valueMapper"); checkArgNotNull(downstream, "downstream"); checkArgNotNull(mapFactory, "mapFactory"); try { final Supplier downstreamSupplier = downstream.supplier(); final BiConsumer downstreamAccumulator = downstream.accumulator(); final Function downstreamFinisher = downstream.finisher(); final M result = mapFactory.get(); final Map tmp = (Map) result; T next = null; K key = null; A container = null; while (elements.hasNext()) { next = elements.next(); key = keyMapper.apply(next); container = tmp.get(key); if (container == null) { container = downstreamSupplier.get(); tmp.put(key, container); } downstreamAccumulator.accept(container, valueMapper.apply(next)); } for (Map.Entry entry : result.entrySet()) { entry.setValue(downstreamFinisher.apply((A) entry.getValue())); } return result; } finally { close(); } } /** * * @param the key type * @param keyMapper * @return * @throws E the e * @see Collectors#groupingBy(Function) */ @TerminalOp public Map> groupTo(Throwables.Function keyMapper) throws E, E2 { return groupTo(keyMapper, Suppliers.> ofMap()); } /** * * @param the key type * @param * @param keyMapper * @param mapFactory * @return * @throws E the e * @see Collectors#groupingBy(Function, Supplier) */ @TerminalOp public >, E2 extends Exception> M groupTo(final Throwables.Function keyMapper, final Supplier mapFactory) throws E, E2 { final Throwables.Function valueMapper = Fnn.identity(); return groupTo(keyMapper, valueMapper, mapFactory); } /** * * @param the key type * @param the value type * @param keyMapper * @param valueMapper * @return * @throws E the e */ @TerminalOp public Map> groupTo(Throwables.Function keyMapper, Throwables.Function valueMapper) throws E, E2, E3 { return groupTo(keyMapper, valueMapper, Suppliers.> ofMap()); } /** * * @param the key type * @param the value type * @param * @param keyMapper * @param valueMapper * @param mapFactory * @return * @throws E the e * @see Collectors#toMultimap(Function, Function, Supplier) */ @TerminalOp public >, E2 extends Exception, E3 extends Exception> M groupTo(Throwables.Function keyMapper, Throwables.Function valueMapper, Supplier mapFactory) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); checkArgNotNull(valueMapper, "valueMapper"); checkArgNotNull(mapFactory, "mapFactory"); try { final M result = mapFactory.get(); T next = null; K key = null; while (elements.hasNext()) { next = elements.next(); key = keyMapper.apply(next); if (result.containsKey(key) == false) { result.put(key, new ArrayList()); } result.get(key).add(valueMapper.apply(next)); } return result; } finally { close(); } } /** * * @param predicate * @return * @see Collectors#partitioningBy(Predicate) */ @TerminalOp public Map> partitionTo(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); return partitionTo(predicate, Collectors. toList()); } /** * * @param predicate * @param downstream * @return * @see Collectors#partitioningBy(Predicate, Collector) */ @TerminalOp public Map partitionTo(final Throwables.Predicate predicate, final Collector downstream) throws E, E2 { assertNotClosed(); final Throwables.Function keyMapper = new Throwables.Function() { @Override public Boolean apply(T t) throws E2 { return predicate.test(t); } }; final Supplier> mapFactory = new Supplier>() { @Override public Map get() { return N. newHashMap(2); } }; final Map map = toMap(keyMapper, downstream, mapFactory); if (map.containsKey(Boolean.TRUE) == false) { map.put(Boolean.TRUE, downstream.finisher().apply(downstream.supplier().get())); } else if (map.containsKey(Boolean.FALSE) == false) { map.put(Boolean.FALSE, downstream.finisher().apply(downstream.supplier().get())); } return map; } @TerminalOp public ListMultimap toMultimap(final Throwables.Function keyMapper) throws E, E2 { return toMultimap(keyMapper, Suppliers. ofListMultimap()); } @TerminalOp public , M extends Multimap, E2 extends Exception> M toMultimap( final Throwables.Function keyMapper, Supplier mapFactory) throws E, E2 { final Throwables.Function valueMapper = Fnn.identity(); return toMultimap(keyMapper, valueMapper, mapFactory); } @TerminalOp public ListMultimap toMultimap(final Throwables.Function keyMapper, final Throwables.Function valueMapper) throws E, E2, E3 { return toMultimap(keyMapper, valueMapper, Suppliers. ofListMultimap()); } @TerminalOp public , M extends Multimap, E2 extends Exception, E3 extends Exception> M toMultimap( final Throwables.Function keyMapper, final Throwables.Function valueMapper, Supplier mapFactory) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(keyMapper, "keyMapper"); checkArgNotNull(valueMapper, "valueMapper"); checkArgNotNull(mapFactory, "mapFactory"); try { final M result = mapFactory.get(); T next = null; while (elements.hasNext()) { next = elements.next(); result.put(keyMapper.apply(next), valueMapper.apply(next)); } return result; } finally { close(); } } @TerminalOp public Multiset toMultiset() throws E { return toMultiset(Suppliers. ofMultiset()); } @TerminalOp public Multiset toMultiset(Supplier> supplier) throws E { assertNotClosed(); checkArgNotNull(supplier, "supplier"); try { final Multiset result = supplier.get(); while (elements.hasNext()) { result.add(elements.next()); } return result; } finally { close(); } } /** * The first row will be used as column names if its type is array or list, * or obtain the column names from first row if its type is entity or map. * * @return * @throws E * @see {@link N#newDataSet(Collection)} */ @TerminalOp public DataSet toDataSet() throws E { return N.newDataSet(toList()); } /** * If the specified {@code columnNames} is null or empty, the first row will be used as column names if its type is array or list, * or obtain the column names from first row if its type is entity or map. * * * @param columnNames * @return * @throws E * @see {@link N#newDataSet(Collection, Collection)} */ @TerminalOp public DataSet toDataSet(List columnNames) throws E { return N.newDataSet(columnNames, toList()); } /** * * @param func * @return * @throws E the e */ @TerminalOp public long sumInt(Throwables.ToIntFunction func) throws E, E2 { assertNotClosed(); try { long sum = 0; while (elements.hasNext()) { sum += func.applyAsInt(elements.next()); } return sum; } finally { close(); } } /** * * @param func * @return * @throws E the e */ @TerminalOp public long sumLong(Throwables.ToLongFunction func) throws E, E2 { assertNotClosed(); try { long sum = 0; while (elements.hasNext()) { sum += func.applyAsLong(elements.next()); } return sum; } finally { close(); } } /** * * @param func * @return * @throws E the e */ @TerminalOp public double sumDouble(Throwables.ToDoubleFunction func) throws E, E2 { assertNotClosed(); try { final KahanSummation summation = new KahanSummation(); while (elements.hasNext()) { summation.add(func.applyAsDouble(elements.next())); } return summation.sum(); } finally { close(); } } /** * * @param func * @return * @throws E the e */ @TerminalOp public OptionalDouble averageInt(Throwables.ToIntFunction func) throws E, E2 { assertNotClosed(); try { if (elements.hasNext() == false) { return OptionalDouble.empty(); } long sum = 0; long count = 0; while (elements.hasNext()) { sum += func.applyAsInt(elements.next()); count++; } return OptionalDouble.of(((double) sum) / count); } finally { close(); } } /** * * @param func * @return * @throws E the e */ @TerminalOp public OptionalDouble averageLong(Throwables.ToLongFunction func) throws E, E2 { assertNotClosed(); try { if (elements.hasNext() == false) { return OptionalDouble.empty(); } long sum = 0; long count = 0; while (elements.hasNext()) { sum += func.applyAsLong(elements.next()); count++; } return OptionalDouble.of(((double) sum) / count); } finally { close(); } } /** * * @param func * @return * @throws E the e */ @TerminalOp public OptionalDouble averageDouble(Throwables.ToDoubleFunction func) throws E, E2 { assertNotClosed(); try { if (elements.hasNext() == false) { return OptionalDouble.empty(); } final KahanSummation summation = new KahanSummation(); while (elements.hasNext()) { summation.add(func.applyAsDouble(elements.next())); } return summation.average(); } finally { close(); } } /** * * @param * @param accumulator * @return * @throws E the e * @throws E2 the e2 */ @TerminalOp public Optional reduce(Throwables.BinaryOperator accumulator) throws E, E2 { assertNotClosed(); checkArgNotNull(accumulator, "accumulator"); try { if (elements.hasNext() == false) { return Optional.empty(); } T result = elements.next(); while (elements.hasNext()) { result = accumulator.apply(result, elements.next()); } return Optional.of(result); } finally { close(); } } /** * * @param * @param * @param identity * @param accumulator * @return * @throws E the e * @throws E2 the e2 */ @TerminalOp public U reduce(final U identity, final Throwables.BiFunction accumulator) throws E, E2 { assertNotClosed(); checkArgNotNull(accumulator, "accumulator"); try { U result = identity; while (elements.hasNext()) { result = accumulator.apply(result, elements.next()); } return result; } finally { close(); } } /** * * @param * @param * @param * @param supplier * @param accumulator * @return * @throws E the e * @throws E2 the e2 * @throws E3 the e3 */ @TerminalOp public R collect(final Throwables.Supplier supplier, final Throwables.BiConsumer accumulator) throws E, E2, E3 { assertNotClosed(); checkArgNotNull(supplier, "supplier"); checkArgNotNull(accumulator, "accumulator"); try { final R result = supplier.get(); while (elements.hasNext()) { accumulator.accept(result, elements.next()); } return result; } finally { close(); } } /** * * @param * @param * @param * @param * @param * @param supplier * @param accumulator * @param finisher * @return * @throws E the e * @throws E2 the e2 * @throws E3 the e3 * @throws E4 the e4 */ @TerminalOp public RR collect(final Throwables.Supplier supplier, final Throwables.BiConsumer accumulator, final Throwables.Function finisher) throws E, E2, E3, E4 { assertNotClosed(); checkArgNotNull(supplier, "supplier"); checkArgNotNull(accumulator, "accumulator"); checkArgNotNull(finisher, "finisher"); try { final R result = supplier.get(); while (elements.hasNext()) { accumulator.accept(result, elements.next()); } return finisher.apply(result); } finally { close(); } } /** * * @param * @param * @param collector * @return * @throws E the e */ @TerminalOp public R collect(final Collector collector) throws E { assertNotClosed(); checkArgNotNull(collector, "collector"); try { final A container = collector.supplier().get(); final BiConsumer accumulator = collector.accumulator(); while (elements.hasNext()) { accumulator.accept(container, elements.next()); } return collector.finisher().apply(container); } finally { close(); } } /** * * @param * @param * @param collector * @return * @throws E the e */ @TerminalOp public R collect(java.util.stream.Collector collector) throws E { assertNotClosed(); checkArgNotNull(collector, "collector"); try { final A container = collector.supplier().get(); final java.util.function.BiConsumer accumulator = collector.accumulator(); while (elements.hasNext()) { accumulator.accept(container, elements.next()); } return collector.finisher().apply(container); } finally { close(); } } /** * Collect and then. * * @param * @param * @param * @param * @param collector * @param func * @return * @throws E the e * @throws E2 the e2 */ @TerminalOp public RR collectAndThen(final Collector collector, final Throwables.Function func) throws E, E2 { assertNotClosed(); checkArgNotNull(collector, "collector"); checkArgNotNull(func, "func"); return func.apply(collect(collector)); } /** * Collect and then. * * @param * @param * @param * @param * @param collector * @param func * @return * @throws E the e * @throws E2 the e2 */ @TerminalOp public RR collectAndThen(final java.util.stream.Collector collector, final Throwables.Function func) throws E, E2 { assertNotClosed(); checkArgNotNull(collector, "collector"); checkArgNotNull(func, "func"); return func.apply(collect(collector)); } @TerminalOp public String join(final CharSequence delimiter) throws E { return join(delimiter, "", ""); } @TerminalOp public String join(CharSequence delimiter, CharSequence prefix, CharSequence suffix) throws E { assertNotClosed(); try { final Joiner joiner = Joiner.with(delimiter, prefix, suffix).reuseCachedBuffer(); while (elements.hasNext()) { joiner.append(elements.next()); } return joiner.toString(); } finally { close(); } } private static final Throwables.Function TO_LINE_OF_STRING = new Throwables.Function() { @Override public String apply(Object t) throws IOException { return N.stringOf(t); } }; public long persist(final File file) throws E, IOException { return persist(TO_LINE_OF_STRING, file); } public long persist(final String header, final String tail, final File file) throws E, IOException { return persist(TO_LINE_OF_STRING, header, tail, file); } /** * toCSV: *
     * final JSONSerializationConfig jsc = JSC.create().setBracketRootValue(false);
     * final Throwables.Function toLine = it -> N.toJSON(it, jsc);
     * stream.persist(toLine, header, outputFile);
     * 
* * @param toLine * @param file * @return * @throws E * @throws IOException */ public long persist(final Throwables.Function toLine, final File file) throws E, IOException { return persist(toLine, null, null, file); } public long persist(final Throwables.Function toLine, final String header, final String tail, final File file) throws E, IOException { assertNotClosed(); final Writer writer = new FileWriter(file); try { return persist(toLine, header, tail, writer); } finally { IOUtil.close(writer); } } public long persist(final Throwables.Function toLine, final OutputStream os) throws E, IOException { assertNotClosed(); final BufferedWriter bw = Objectory.createBufferedWriter(os); try { return persist(toLine, bw); } finally { Objectory.recycle(bw); } } /** * toCSV: *
     * final JSONSerializationConfig jsc = JSC.create().setBracketRootValue(false);
     * final Throwables.Function toLine = it -> N.toJSON(it, jsc);
     * stream.persist(toLine, header, outputFile);
     * 
* * @param toLine * @param writer * @return * @throws E * @throws IOException */ public long persist(Throwables.Function toLine, Writer writer) throws E, IOException { assertNotClosed(); return persist(toLine, null, null, writer); } public long persist(Throwables.Function toLine, String header, String tail, Writer writer) throws E, IOException { assertNotClosed(); try { boolean isBufferedWriter = writer instanceof BufferedWriter || writer instanceof java.io.BufferedWriter; final Writer bw = isBufferedWriter ? writer : Objectory.createBufferedWriter(writer); final ExceptionalIterator iter = iteratorEx(); long cnt = 0; try { if (header != null) { bw.write(header); bw.write(IOUtil.LINE_SEPARATOR); } while (iter.hasNext()) { bw.write(toLine.apply(iter.next())); bw.write(IOUtil.LINE_SEPARATOR); cnt++; } if (tail != null) { bw.write(tail); bw.write(IOUtil.LINE_SEPARATOR); } bw.flush(); } finally { if (!isBufferedWriter) { Objectory.recycle((BufferedWriter) bw); } } return cnt; } finally { close(); } } public long persist(final Throwables.BiConsumer writeLine, final File file) throws E, IOException { assertNotClosed(); return persist(writeLine, null, null, file); } public long persist(final Throwables.BiConsumer writeLine, final String header, final String tail, final File file) throws E, IOException { assertNotClosed(); final Writer writer = new FileWriter(file); try { return persist(writeLine, header, tail, writer); } finally { IOUtil.close(writer); } } public long persist(final Throwables.BiConsumer writeLine, final Writer writer) throws E, IOException { assertNotClosed(); return persist(writeLine, null, null, writer); } public long persist(final Throwables.BiConsumer writeLine, final String header, final String tail, final Writer writer) throws E, IOException { assertNotClosed(); try { boolean isBufferedWriter = writer instanceof BufferedWriter || writer instanceof java.io.BufferedWriter; final Writer bw = isBufferedWriter ? writer : Objectory.createBufferedWriter(writer); final ExceptionalIterator iter = iteratorEx(); long cnt = 0; try { if (header != null) { bw.write(header); bw.write(IOUtil.LINE_SEPARATOR); } while (iter.hasNext()) { writeLine.accept(iter.next(), writer); bw.write(IOUtil.LINE_SEPARATOR); cnt++; } if (tail != null) { bw.write(tail); bw.write(IOUtil.LINE_SEPARATOR); } bw.flush(); } finally { if (!isBufferedWriter) { Objectory.recycle((BufferedWriter) bw); } } return cnt; } finally { close(); } } public long persist(final Connection conn, final String insertSQL, final int batchSize, final int batchInterval, final Throwables.BiConsumer stmtSetter) throws E, SQLException { assertNotClosed(); PreparedStatement stmt = null; try { stmt = conn.prepareStatement(insertSQL); return persist(stmt, batchSize, batchInterval, stmtSetter); } finally { IOUtil.closeQuietly(stmt); } } public long persist(final PreparedStatement stmt, final int batchSize, final int batchInterval, final Throwables.BiConsumer stmtSetter) throws E, SQLException { assertNotClosed(); checkArgument(batchSize > 0 && batchInterval >= 0, "'batchSize'=%s must be greater than 0 and 'batchInterval'=%s can't be negative", batchSize, batchInterval); try { final ExceptionalIterator iter = iteratorEx(); long cnt = 0; while (iter.hasNext()) { stmtSetter.accept(iter.next(), stmt); stmt.addBatch(); if ((++cnt % batchSize) == 0) { executeBatch(stmt); if (batchInterval > 0) { N.sleep(batchInterval); } } } if ((cnt % batchSize) > 0) { executeBatch(stmt); } return cnt; } finally { close(); } } private int[] executeBatch(final PreparedStatement stmt) throws SQLException { try { return stmt.executeBatch(); } finally { try { stmt.clearBatch(); } catch (SQLException e) { logger.error("Failed to clear batch parameters after executeBatch", e); } } } @TerminalOp @Beta public void println() throws E { N.println(join(", ", "[", "]")); } @IntermediateOp public java.util.stream.Stream toJdkStream() { assertNotClosed(); final Spliterator spliterator = Spliterators.spliteratorUnknownSize(newObjIterator(elements), Spliterator.ORDERED); if (N.isNullOrEmpty(closeHandlers)) { return StreamSupport.stream(() -> spliterator, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL, false); } else { return StreamSupport.stream(() -> spliterator, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL, false).onClose(new Runnable() { @Override public void run() { try { ExceptionalStream.this.close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } }); } } @IntermediateOp @Beta public ExceptionalStream cast() { assertNotClosed(); return (ExceptionalStream) this; } /** * * @param * @param transfer * @return * @throws E the e */ @IntermediateOp @Beta public ExceptionalStream __(Function, ExceptionalStream> transfer) { assertNotClosed(); checkArgNotNull(transfer, "transfer"); return transfer.apply(this); } /** * * @param predicate * @return */ @SuppressWarnings("rawtypes") @IntermediateOp @Beta public ExceptionalStream filterE(final Throwables.Predicate predicate) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws Exception { if (hasNext == false) { while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { hasNext = true; break; } } } return hasNext; } @Override public T next() throws Exception { if (hasNext == false && hasNext() == false) { throw new NoSuchElementException(); } hasNext = false; return next; } }, sorted, cmp, (Deque) closeHandlers); } /** * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @IntermediateOp @Beta public ExceptionalStream mapE(final Throwables.Function mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws Exception { return elements.hasNext(); } @Override public U next() throws Exception { return mapper.apply(elements.next()); } }, (Deque) closeHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp @Beta public ExceptionalStream flatMapE( final Throwables.Function, ? extends Exception> mapper) { assertNotClosed(); final ExceptionalIterator iter = new ExceptionalIterator() { private ExceptionalIterator cur = null; private ExceptionalStream s = null; private Deque> closeHandle = null; @Override public boolean hasNext() throws Exception { while (cur == null || cur.hasNext() == false) { if (elements.hasNext()) { if (closeHandle != null) { final Deque> tmp = closeHandle; closeHandle = null; ExceptionalStream.close(tmp); } s = mapper.apply(elements.next()); if (s == null) { cur = null; } else { if (N.notNullOrEmpty(s.closeHandlers)) { closeHandle = s.closeHandlers; } cur = s.elements; } } else { cur = null; break; } } return cur != null && cur.hasNext(); } @Override public R next() throws Exception { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } @Override public void close() throws Exception { if (closeHandle != null) { ExceptionalStream.close(closeHandle); } } }; final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); newCloseHandlers.add(new Throwables.Runnable() { @Override public void run() throws Exception { iter.close(); } }); if (N.notNullOrEmpty(closeHandlers)) { newCloseHandlers.addAll(closeHandlers); } return newStream(iter, newCloseHandlers); } /** * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @IntermediateOp @Beta public ExceptionalStream flattMapE(final Throwables.Function, ? extends Exception> mapper) { assertNotClosed(); return newStream(new ExceptionalIterator() { private Iterator cur = null; private Collection c = null; @Override public boolean hasNext() throws Exception { while ((cur == null || cur.hasNext() == false) && elements.hasNext()) { c = mapper.apply(elements.next()); cur = N.isNullOrEmpty(c) ? null : c.iterator(); } return cur != null && cur.hasNext(); } @Override public R next() throws Exception { if ((cur == null || cur.hasNext() == false) && hasNext() == false) { throw new NoSuchElementException(); } return cur.next(); } }, (Deque) closeHandlers); } /** * * @param action * @return */ @SuppressWarnings("rawtypes") @IntermediateOp @Beta public ExceptionalStream onEachE(final Throwables.Consumer action) { assertNotClosed(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws Exception { return elements.hasNext(); } @Override public T next() throws Exception { final T next = elements.next(); action.accept(next); return next; } }, sorted, cmp, (Deque) closeHandlers); } /** * * @param closeHandler * @return */ @IntermediateOp public ExceptionalStream onClose(final Throwables.Runnable closeHandler) { assertNotClosed(); checkArgNotNull(closeHandler, "closeHandler"); final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); newCloseHandlers.add(new Throwables.Runnable() { private volatile boolean isClosed = false; @Override public void run() throws E { if (isClosed) { return; } isClosed = true; closeHandler.run(); } }); if (N.notNullOrEmpty(this.closeHandlers)) { newCloseHandlers.addAll(this.closeHandlers); } return newStream(elements, newCloseHandlers); } /** * * @throws E the e */ @TerminalOp @Override public synchronized void close() { if (isClosed) { return; } if (N.isNullOrEmpty(closeHandlers)) { isClosed = true; return; } // // Only mark the stream closed if closeHandlers are not empty. // if (isClosed || N.isNullOrEmpty(closeHandlers)) { // return; // } isClosed = true; logger.debug("Closing ExceptionalStream"); close(closeHandlers); } static void close(final Deque> closeHandlers) { Throwable ex = null; for (Throwables.Runnable closeHandler : closeHandlers) { try { closeHandler.run(); } catch (Exception e) { if (ex == null) { ex = e; } else { ex.addSuppressed(e); } } } if (ex != null) { throw ExceptionUtil.toRuntimeException(ex); } } ExceptionalIterator iteratorEx() { return elements; } /** * Assert not closed. */ void assertNotClosed() { if (isClosed) { throw new IllegalStateException("This stream has been closed"); } } /** * Check arg positive. * * @param arg * @param argNameOrErrorMsg * @return */ private int checkArgPositive(final int arg, final String argNameOrErrorMsg) { if (arg <= 0) { try { N.checkArgPositive(arg, argNameOrErrorMsg); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } } return arg; } /** * Check arg not negative. * * @param arg * @param argNameOrErrorMsg * @return */ private long checkArgNotNegative(final long arg, final String argNameOrErrorMsg) { if (arg < 0) { try { N.checkArgNotNegative(arg, argNameOrErrorMsg); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } } return arg; } /** * Check arg not null. * * @param * @param obj * @param errorMessage * @return */ private ARG checkArgNotNull(final ARG obj, final String errorMessage) { if (obj == null) { try { N.checkArgNotNull(obj, errorMessage); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } } return obj; } /** * * @param b * @param errorMessage */ private void checkArgument(boolean b, String errorMessage) { if (!b) { try { N.checkArgument(b, errorMessage); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } } } /** * * @param b * @param errorMessageTemplate * @param p1 * @param p2 */ private void checkArgument(boolean b, String errorMessageTemplate, int p1, int p2) { if (!b) { try { N.checkArgument(b, errorMessageTemplate, p1, p2); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } } } ObjIterator newObjIterator(final ExceptionalIterator elements) { return new ObjIterator() { @Override public boolean hasNext() { try { return elements.hasNext(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } @Override public T next() { try { return elements.next(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } }; } /** * * @param * @param * @param iter * @return */ static ExceptionalStream newStream(final ExceptionalIterator iter) { return new ExceptionalStream<>(iter, null); } /** * * @param * @param * @param iter * @param closeHandlers * @return */ static ExceptionalStream newStream(final ExceptionalIterator iter, final Deque> closeHandlers) { return new ExceptionalStream<>(iter, closeHandlers); } /** * * @param * @param * @param iter * @param sorted * @param comparator * @param closeHandlers * @return */ static ExceptionalStream newStream(final ExceptionalIterator iter, final boolean sorted, final Comparator comparator, final Deque> closeHandlers) { return new ExceptionalStream<>(iter, sorted, comparator, closeHandlers); } /** * * @param obj * @return */ static Object hashKey(Object obj) { return obj == null || obj.getClass().isArray() == false ? obj : Wrapper.of(obj); } /** * Checks if is same comparator. * * @param a * @param b * @return true, if is same comparator */ static boolean isSameComparator(Comparator a, Comparator b) { return a == b || (a == null && b == Comparators.NATURAL_ORDER) || (b == null && a == Comparators.NATURAL_ORDER); } static ExceptionalIterator iterate(final ExceptionalStream s) { return s == null ? ExceptionalIterator.EMPTY : (ExceptionalIterator) iterate(s); } /** * The Class ExceptionalIterator. * * @param * @param */ @com.landawn.abacus.annotation.Immutable static abstract class ExceptionalIterator implements Immutable { /** The Constant EMPTY. */ @SuppressWarnings("rawtypes") private static final ExceptionalIterator EMPTY = new ExceptionalIterator() { @Override public boolean hasNext() throws Exception { return false; } @Override public Object next() throws Exception { throw new NoSuchElementException(); } }; public static ExceptionalIterator wrap(final Iterator iter) { if (iter == null) { return EMPTY; } return new ExceptionalIterator() { @Override public boolean hasNext() throws E { return iter.hasNext(); } @Override public T next() throws E { return iter.next(); } }; } /** * Lazy evaluation. * * @param * @param * @param iteratorSupplier * @return */ public static ExceptionalIterator of(final Throwables.Supplier, E> iteratorSupplier) { N.checkArgNotNull(iteratorSupplier, "iteratorSupplier"); return new ExceptionalIterator() { private ExceptionalIterator iter = null; private boolean isInitialized = false; @Override public boolean hasNext() throws E { if (isInitialized == false) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (isInitialized == false) { init(); } return iter.next(); } @Override public void advance(long n) throws E { N.checkArgNotNegative(n, "n"); if (isInitialized == false) { init(); } iter.advance(n); } @Override public long count() throws E { if (isInitialized == false) { init(); } return iter.count(); } @Override public void close() throws E { if (isInitialized == false) { init(); } iter.close(); } private void init() throws E { if (isInitialized == false) { isInitialized = true; iter = iteratorSupplier.get(); } } }; } /** * Lazy evaluation. * * @param * @param * @param arraySupplier * @return */ public static ExceptionalIterator oF(final Throwables.Supplier arraySupplier) { N.checkArgNotNull(arraySupplier, "arraySupplier"); return new ExceptionalIterator() { private T[] a; private int len; private int position = 0; private boolean isInitialized = false; @Override public boolean hasNext() throws E { if (isInitialized == false) { init(); } return position < len; } @Override public T next() throws E { if (isInitialized == false) { init(); } if (position >= len) { throw new NoSuchElementException(); } return a[position++]; } @Override public long count() throws E { if (isInitialized == false) { init(); } return len - position; } @Override public void advance(long n) throws E { N.checkArgNotNegative(n, "n"); if (isInitialized == false) { init(); } if (n > len - position) { position = len; } else { position += n; } } private void init() throws E { if (isInitialized == false) { isInitialized = true; a = arraySupplier.get(); len = N.len(a); } } }; } /** * Checks for next. * * @return * @throws E the e */ public abstract boolean hasNext() throws E; /** * * @return * @throws E the e */ public abstract T next() throws E; /** * * @param n * @throws E the e */ public void advance(long n) throws E { N.checkArgNotNegative(n, "n"); while (n-- > 0 && hasNext()) { next(); } } /** * * @return * @throws E the e */ public long count() throws E { long result = 0; while (hasNext()) { next(); result++; } return result; } /** * * @throws E the e */ public void close() throws E { // Nothing to do by default. } } // CheckedException -> Maybe makes sense. Checked exception... // But what does CheckedStream mean? Checked stream ??? // public static final class CheckedStream extends ExceptionalStream { // // CheckedStream(ExceptionalIterator iter, boolean sorted, Comparator comparator, Deque> closeHandlers) { // super(iter, sorted, comparator, closeHandlers); // } // } /** * * @param * @param */ public static final class StreamE extends ExceptionalStream { StreamE(ExceptionalIterator iter, boolean sorted, Comparator comparator, Deque> closeHandlers) { super(iter, sorted, comparator, closeHandlers); } } // /** // * Mostly it's for android. // * // * @see {@code ExceptionalStream} // * // * @deprecated Mostly it's for android. // */ // @Deprecated // @Beta // public static final class StreamR extends Seq { // private StreamR() { // // singleton for utility class. // } // } /** * Mostly it's for android. * * @see {@code ExceptionalStream} */ @Beta public final static class Seq { private Seq() { // singleton for utility class. } public static ExceptionalStream empty() { return ExceptionalStream. empty(); } public static ExceptionalStream just(final T e) { return ExceptionalStream. just(e); } public static ExceptionalStream ofNullable(final T e) { return ExceptionalStream. ofNullable(e); } public static ExceptionalStream of(final T... a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final Collection c) { return ExceptionalStream. of(c); } public static ExceptionalStream of(final Iterator iter) { return ExceptionalStream. of(iter); } public static ExceptionalStream of(final Iterable iterable) { return ExceptionalStream. of(iterable); } public static ExceptionalStream, RuntimeException> of(final Map m) { return ExceptionalStream. of(m); } public static ExceptionalStream of(final boolean[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final char[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final byte[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final short[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final int[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final long[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final float[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final double[] a) { return ExceptionalStream. of(a); } public static ExceptionalStream of(final Optional op) { return ExceptionalStream. of(op); } public static ExceptionalStream of(final java.util.Optional op) { return ExceptionalStream. of(op); } public static ExceptionalStream of(final Throwables.Supplier, RuntimeException> supplier) { return ExceptionalStream. of(supplier); } public static ExceptionalStream from( final Throwables.Supplier, RuntimeException> supplier) { return ExceptionalStream. from(supplier); } public static ExceptionalStream ofKeys(final Map map) { return ExceptionalStream. ofKeys(map); } public static ExceptionalStream ofKeys(final Map map, final Throwables.Predicate valueFilter) { return ExceptionalStream. ofKeys(map, valueFilter); } public static ExceptionalStream ofKeys(final Map map, final Throwables.BiPredicate filter) { return ExceptionalStream.ofKeys(map, filter); } public static ExceptionalStream ofValues(final Map map) { return ExceptionalStream. ofValues(map); } public static ExceptionalStream ofValues(final Map map, final Throwables.Predicate keyFilter) { return ExceptionalStream. ofValues(map, keyFilter); } public static ExceptionalStream ofValues(final Map map, final Throwables.BiPredicate filter) { return ExceptionalStream.ofValues(map, filter); } public static ExceptionalStream iterate(final Throwables.BooleanSupplier hasNext, final Throwables.Supplier next) { return ExceptionalStream. iterate(hasNext, next); } public static ExceptionalStream iterate(final T init, final Throwables.BooleanSupplier hasNext, final Throwables.UnaryOperator f) { return ExceptionalStream. iterate(init, hasNext, f); } public static ExceptionalStream iterate(final T init, final Throwables.Predicate hasNext, final Throwables.UnaryOperator f) { return ExceptionalStream. iterate(init, hasNext, f); } public static ExceptionalStream iterate(final T init, final Throwables.UnaryOperator f) { return ExceptionalStream. iterate(init, f); } public static ExceptionalStream generate(final Throwables.Supplier supplier) { return ExceptionalStream. generate(supplier); } public static ExceptionalStream repeat(final T element, final long n) { return ExceptionalStream. repeat(element, n); } public static ExceptionalStream range(final int startInclusive, final int endExclusive) { return ExceptionalStream. range(startInclusive, endExclusive); } public static ExceptionalStream range(final int startInclusive, final int endExclusive, final int by) { return ExceptionalStream. range(startInclusive, endExclusive, by); } public static ExceptionalStream rangeClosed(final int startInclusive, final int endExclusive) { return ExceptionalStream. rangeClosed(startInclusive, endExclusive); } public static ExceptionalStream rangeClosed(final int startInclusive, final int endExclusive, final int by) { return ExceptionalStream. rangeClosed(startInclusive, endExclusive, by); } @SafeVarargs public static ExceptionalStream concat(final T[]... a) { return ExceptionalStream. concat(a); } @SafeVarargs public static ExceptionalStream concat(final Collection... a) { return ExceptionalStream. concat(a); } public static ExceptionalStream zip(final A[] a, final B[] b, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, zipFunction); } public static ExceptionalStream zip(final A[] a, final B[] b, final C[] c, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, zipFunction); } public static ExceptionalStream zip(final Collection a, final Collection b, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, zipFunction); } public static ExceptionalStream zip(final Collection a, final Collection b, final Collection c, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, zipFunction); } public static ExceptionalStream zip(final Iterator a, final Iterator b, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, zipFunction); } public static ExceptionalStream zip(final Iterator a, final Iterator b, final Iterator c, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, zipFunction); } public static ExceptionalStream zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, valueForNoneA, valueForNoneB, zipFunction); } public static ExceptionalStream zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } public static ExceptionalStream zip(final Collection a, final Collection b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, valueForNoneA, valueForNoneB, zipFunction); } public static ExceptionalStream zip(final Collection a, final Collection b, final Collection c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } public static ExceptionalStream zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction zipFunction) { return ExceptionalStream. zip(a, b, valueForNoneA, valueForNoneB, zipFunction); } public static ExceptionalStream zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction zipFunction) { return ExceptionalStream. zip(a, b, c, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction); } public static ExceptionalStream merge(final T[] a, final T[] b, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, nextSelector); } public static ExceptionalStream merge(final T[] a, final T[] b, final T[] c, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, c, nextSelector); } public static ExceptionalStream merge(final Collection a, final Collection b, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, nextSelector); } public static ExceptionalStream merge(final Collection a, final Collection b, final Collection c, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, c, nextSelector); } public static ExceptionalStream merge(final Iterator a, final Iterator b, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, nextSelector); } public static ExceptionalStream merge(final Iterator a, final Iterator b, final Iterator c, final Throwables.BiFunction nextSelector) { return ExceptionalStream. merge(a, b, c, nextSelector); } } }