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.

There is a newer version: 5.2.4
Show 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.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.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.concurrent.Executor;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.StreamSupport;

import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.IntermediateOp;
import com.landawn.abacus.annotation.Internal;
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.TooManyElementsException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.parser.JSONParser;
import com.landawn.abacus.parser.JSONSerializationConfig;
import com.landawn.abacus.parser.JSONSerializationConfig.JSC;
import com.landawn.abacus.parser.ParserFactory;
import com.landawn.abacus.parser.ParserUtil;
import com.landawn.abacus.parser.ParserUtil.BeanInfo;
import com.landawn.abacus.parser.ParserUtil.PropInfo;
import com.landawn.abacus.type.Type;
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.Strings.StringUtil;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalInt;
import com.landawn.abacus.util.u.OptionalLong;
import com.landawn.abacus.util.stream.Collectors;
import com.landawn.abacus.util.stream.DoubleStream;
import com.landawn.abacus.util.stream.IntStream;
import com.landawn.abacus.util.stream.LongStream;
import com.landawn.abacus.util.stream.ObjIteratorEx;
import com.landawn.abacus.util.stream.Stream;

/**
 * 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
@SuppressWarnings("java:S1192")
public class ExceptionalStream implements Closeable, Immutable {

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

    static final Object NONE = N.NULL_MASK;

    static final Random RAND = new SecureRandom();

    static final Throwables.Function GET_AS_INT = OptionalInt::get;

    static final Throwables.Function GET_AS_LONG = OptionalLong::get;

    static final Throwables.Function GET_AS_DOUBLE = OptionalDouble::get;

    @SuppressWarnings("rawtypes")
    static final Throwables.Function GET_AS_IT = it -> it.orElse(null);

    static final Throwables.Function GET_AS_INT_JDK = java.util.OptionalInt::getAsInt;

    static final Throwables.Function GET_AS_LONG_JDK = java.util.OptionalLong::getAsLong;

    static final Throwables.Function GET_AS_DOUBLE_JDK = java.util.OptionalDouble::getAsDouble;

    @SuppressWarnings("rawtypes")
    static final Throwables.Function GET_AS_IT_JDK = it -> it.orElse(null);

    static final Throwables.Predicate IS_PRESENT_INT = OptionalInt::isPresent;

    static final Throwables.Predicate IS_PRESENT_LONG = OptionalLong::isPresent;

    static final Throwables.Predicate IS_PRESENT_DOUBLE = OptionalDouble::isPresent;

    @SuppressWarnings("rawtypes")
    static final Throwables.Predicate IS_PRESENT_IT = Optional::isPresent;

    static final Throwables.Predicate IS_PRESENT_INT_JDK = java.util.OptionalInt::isPresent;

    static final Throwables.Predicate IS_PRESENT_LONG_JDK = java.util.OptionalLong::isPresent;

    static final Throwables.Predicate IS_PRESENT_DOUBLE_JDK = java.util.OptionalDouble::isPresent;

    @SuppressWarnings("rawtypes")
    static final Throwables.Predicate IS_PRESENT_IT_JDK = java.util.Optional::isPresent;

    static final Throwables.Function, Object>, Object, Exception> KK = t -> 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) { //NOSONAR
        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);
    }

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

        return of(e);
    }

    /**
     *
     * @param 
     * @param 
     * @param a
     * @return
     * @see Stream.of(T[]).checked(SomeCheckedException.class)...
     */
    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; //NOSONAR
            }

            @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; //NOSONAR
                }

                @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. of(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 stream
     * @return
     */
    public static  ExceptionalStream of(final Stream stream) {
        return checked(stream, false);
    }

    /**
     *
     * @param 
     * @param 
     * @param stream
     * @return
     */
    public static  ExceptionalStream of(final java.util.stream.Stream stream) {
        if (stream == null) {
            return empty();
        }

        return ExceptionalStream. of(stream.iterator()).onClose(stream::close);
    }

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

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

    /**
     *
     * @param 
     * @param 
     * @param iterable
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream of(final Iterable iterable,
            @SuppressWarnings("unused") final Class exceptionType) { //NOSONAR
        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) { //NOSONAR
        return of(m);
    }

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

    /**
     *
     * @param 
     * @param 
     * @param stream
     * @param exceptionType
     * @return
     */
    public static  ExceptionalStream of(final java.util.stream.Stream stream,
            @SuppressWarnings("unused") final Class exceptionType) { //NOSONAR
        return of(stream);
    }

    /**
     *
     *
     * @param 
     * @param a
     * @return
     */
    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; //NOSONAR
            }

            @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 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; //NOSONAR
            }

            @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 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; //NOSONAR
            }

            @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 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; //NOSONAR
            }

            @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; //NOSONAR
            }

            @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; //NOSONAR
            }

            @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 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; //NOSONAR
            }

            @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; //NOSONAR
            }

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

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

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

    /**
     *
     *
     * @param 
     * @param 
     * @param map
     * @return
     */
    public static  ExceptionalStream ofKeys(final Map map) {
        if (N.isNullOrEmpty(map)) {
            return empty();
        }

        return of(map.keySet());
    }

    /**
     *
     *
     * @param 
     * @param 
     * @param 
     * @param map
     * @param valueFilter
     * @return
     */
    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());
    }

    /**
     *
     *
     * @param 
     * @param 
     * @param 
     * @param map
     * @param filter
     * @return
     */
    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());
    }

    /**
     *
     *
     * @param 
     * @param 
     * @param map
     * @return
     */
    public static  ExceptionalStream ofValues(final Map map) {
        if (N.isNullOrEmpty(map)) {
            return empty();
        }

        return of(map.values());
    }

    /**
     *
     *
     * @param 
     * @param 
     * @param 
     * @param map
     * @param keyFilter
     * @return
     */
    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());
    }

    /**
     *
     *
     * @param 
     * @param 
     * @param 
     * @param map
     * @param filter
     * @return
     */
    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());
    }

    //    /**
    //     * Lazy evaluation.
    //     * 
// * // * This is equal to: {@code ExceptionalStream.just(supplier).flatmap(it -> it.get())}. // * // * @param supplier // * @return // */ // @Beta // public static ExceptionalStream from(final Throwables.Supplier, ? extends E> supplier) { // N.checkArgNotNull(supplier, "supplier"); // // return ExceptionalStream., ? extends E>, E> just(supplier) // .flatmap(Throwables.Supplier::get); // } /** * Lazy evaluation. *
* * This is equal to: {@code ExceptionalStream.just(supplier).flatMap(it -> it.get())}. * * @param * @param * @param supplier * @return */ public static ExceptionalStream defer( final Throwables.Supplier, ? extends E> supplier) { N.checkArgNotNull(supplier, "supplier"); return ExceptionalStream., ? extends E>, E> just(supplier) .flatMap(Throwables.Supplier::get); } /** * * @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) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() throws E { if (!hasNextVal && !hasNext()) { 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) NONE; private T t = none; private boolean hasNextVal = false; @Override public boolean hasNext() throws E { if (!hasNextVal) { hasNextVal = hasNext.getAsBoolean(); } return hasNextVal; } @Override public T next() throws E { if (!hasNextVal && !hasNext()) { 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) NONE; private T t = none; private T cur = none; private boolean hasMore = true; private boolean hasNextVal = false; @Override public boolean hasNext() throws E { if (!hasNextVal && hasMore) { hasNextVal = hasNext.test((cur = (t == none ? init : f.apply(t)))); if (!hasNextVal) { hasMore = false; } } return hasNextVal; } @Override public T next() throws E { if (!hasNextVal && !hasNext()) { 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) NONE; 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); } }); } /** * * * @param * @param * @param supplier * @return */ 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(); } }); } /** * * * @param * @param * @param element * @param n * @return */ 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; } }); } /** * * * @param * @param startInclusive * @param endExclusive * @return */ public static ExceptionalStream range(final int startInclusive, final int endExclusive) { return IntStream.range(startInclusive, endExclusive).boxed(). checked(); } /** * * * @param * @param startInclusive * @param endExclusive * @param by * @return */ public static ExceptionalStream range(final int startInclusive, final int endExclusive, final int by) { return IntStream.range(startInclusive, endExclusive, by).boxed(). checked(); } /** * * * @param * @param startInclusive * @param endExclusive * @return */ public static ExceptionalStream rangeClosed(final int startInclusive, final int endExclusive) { return IntStream.rangeClosed(startInclusive, endExclusive).boxed(). checked(); } /** * * * @param * @param startInclusive * @param endExclusive * @param by * @return */ public static ExceptionalStream rangeClosed(final int startInclusive, final int endExclusive, final int by) { return IntStream.rangeClosed(startInclusive, endExclusive, by).boxed(). checked(); } /** * * * @param * @param str * @param delimiter * @return */ public static ExceptionalStream split(final CharSequence str, final CharSequence delimiter) { return of(Splitter.with(delimiter).iterate(str)); } /** * * @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(newCloseHandler(iter)); //NOSONAR } /** * * @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(newCloseHandler(iter)); } /** * * @param reader * @return */ public static ExceptionalStream lines(final Reader reader) { N.checkArgNotNull(reader, "reader"); return newStream(createLazyLineIterator(null, null, Charsets.UTF_8, reader, false)); } /** * * * @param parentPath * @return */ public static ExceptionalStream listFiles(final File parentPath) { if (!parentPath.exists()) { return empty(); } return of(parentPath.listFiles()); } /** * * * @param parentPath * @param recursively * @return */ public static ExceptionalStream listFiles(final File parentPath, final boolean recursively) { if (!parentPath.exists()) { return empty(); } else if (!recursively) { 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()) { 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.defer(new Throwables.Supplier, IOException>() { private ExceptionalIterator lazyIter = null; @Override public synchronized ExceptionalIterator get() { if (lazyIter == null) { lazyIter = new ExceptionalIterator<>() { private BufferedReader bufferedReader; { //NOSONAR 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; } }); } /** * * * @param * @param * @param a * @return */ @SafeVarargs public static ExceptionalStream concat(final T[]... a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(Iterators.concat(a)); } /** * * * @param * @param * @param a * @return */ @SafeVarargs public static ExceptionalStream concat(final Iterable... a) { if (N.isNullOrEmpty(a)) { return empty(); } return of(Iterators.concat(a)); } /** * * * @param * @param * @param a * @return */ @SafeVarargs public static ExceptionalStream concat(final Iterator... 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()) && 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()) && !hasNext()) { 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 * @param * @param * @param * @param a * @param b * @param zipFunction * @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 * @param * @param * @param * @param * @param a * @param b * @param c * @param zipFunction * @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 * @param * @param * @param * @param a * @param b * @param zipFunction * @return */ public static ExceptionalStream zip(final Iterable a, final Iterable 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 * @param * @param * @param * @param * @param a * @param b * @param c * @param zipFunction * @return */ public static ExceptionalStream zip(final Iterable a, final Iterable b, final Iterable 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 * @param * @param * @param * @param a * @param b * @param zipFunction * @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 * @param * @param * @param * @param * @param a * @param b * @param c * @param zipFunction * @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 * @param * @param * @param * @param a * @param b * @param zipFunction * @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 * @param * @param * @param * @param * @param a * @param b * @param c * @param zipFunction * @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 * @param * @param * @param * @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 * @param * @param * @param * @param * @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 * @param * @param * @param * @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 Iterable a, final Iterable 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 * @param * @param * @param * @param * @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 Iterable a, final Iterable b, final Iterable 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 * @param * @param * @param * @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()) { 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 * @param * @param * @param * @param * @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()) { 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 * @param * @param * @param * @param a * @param b * @param valueForNoneA * @param valueForNoneB * @param zipFunction * @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()) { 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 * @param * @param * @param * @param * @param a * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @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()) { 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 (s.isClosed || isEmptyCloseHandlers(s.closeHandlers)) { continue; } newCloseHandlers.addAll(s.closeHandlers); } return newCloseHandlers; } /** * * * @param * @param * @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 * @param * @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. of(N.iterate(c)), nextSelector); } /** * * * @param * @param * @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 Iterable a, final Iterable b, final Throwables.BiFunction nextSelector) { return merge(N.iterate(a), N.iterate(b), nextSelector); } /** * * * @param * @param * @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 Iterable a, final Iterable b, final Iterable c, final Throwables.BiFunction nextSelector) { return merge(N.iterate(a), N.iterate(b), N.iterate(c), nextSelector); } /** * * * @param * @param * @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. of(a), ExceptionalIterator. of(b), nextSelector); } /** * * * @param * @param * @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. of(c), nextSelector); } /** * * * @param * @param * @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(() -> { try { if (a != null) { a.close(); } } finally { if (b != null) { b.close(); } } }); } /** * * * @param * @param * @param a * @param b * @param c * @param nextSelector * @return */ 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) { while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { hasNext = true; break; } } } return hasNext; } @Override public T next() throws E { if (!hasNext && !hasNext()) { 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(value -> { 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 && 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 && !hasNext()) { 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) { if (!dropped) { dropped = true; while (elements.hasNext()) { next = elements.next(); if (!predicate.test(next)) { hasNext = true; break; } } } else if (elements.hasNext()) { next = elements.next(); hasNext = true; } } return hasNext; } @Override public T next() throws E { if (!hasNext && !hasNext()) { 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 dropWhile(value -> { if (!predicate.test(value)) { actionOnDroppedItem.accept(value); return false; } return true; }); } /** * * @param predicate * @return */ @Beta @IntermediateOp 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(value -> set.add(hashKey(value))); } /** * Distinct and filter by occurrences. * * @param mergeFunction * @return * @see #groupBy(Function, Function, BinaryOperator) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream distinct(final Throwables.BinaryOperator mergeFunction) { return distinctBy(Fnn.identity(), mergeFunction); } /** * Distinct and filter by occurrences. * * @param occurrencesFilter * @return * @see #groupBy(Function, Collector) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream distinct(final Throwables.Predicate occurrencesFilter) { return distinctBy(Fnn.identity(), occurrencesFilter); } /** * Distinct by the value mapped from keyMapper . * * @param * @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(value -> set.add(hashKey(keyMapper.apply(value)))); } /** * Distinct and filter by occurrences. * * @param * @param keyMapper * @param mergeFunction * @return * @see #groupBy(Function, Function, BinaryOperator) */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream distinctBy(final Throwables.Function keyMapper, final Throwables.BinaryOperator mergeFunction) { assertNotClosed(); final Supplier> supplier = Suppliers. ofMap(); return groupBy(keyMapper, Fnn. identity(), mergeFunction, supplier).map(Fnn. value()); } /** * Distinct and filter by occurrences. * * @param * @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 = t -> Keyed.of(keyMapper.apply(t), t); final Throwables.Predicate, Long>, ? extends E> predicate = e -> occurrencesFilter.test(e.getValue()); return newStream(groupBy(keyedMapper, Collectors.counting(), supplier).filter(predicate) .map((Throwables.Function, Long>, T, E>) (Throwables.Function) KK) .iteratorEx(), sorted, cmp, closeHandlers); } /** * * @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 R next() throws E { return mapper.apply(elements.next()); } }, closeHandlers); } /** * * * @param mapperForFirst * @return */ @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); } /** * * * @param * @param mapperForFirst * @param mapperForElse * @return */ @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); } /** * * * @param mapperForLast * @return */ @IntermediateOp public ExceptionalStream mapLast(final Throwables.Function mapperForLast) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || elements.hasNext(); } @Override public T next() throws E { next = elements.next(); if (hasNext = elements.hasNext()) { return next; } else { return mapperForLast.apply(next); } } }, closeHandlers); } /** * * * @param * @param mapperForLast * @param mapperForElse * @return */ @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); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flatMap( final Throwables.Function, ? extends E> mapper) { assertNotClosed(); final ExceptionalIterator iter = new ExceptionalIterator<>() { private ExceptionalStream s = null; private ExceptionalIterator cur = null; @Override public boolean hasNext() throws E { while (cur == null || !cur.hasNext()) { if (elements.hasNext()) { if (s != null) { s.close(); s = null; } s = mapper.apply(elements.next()); if (s == null) { cur = null; } else { cur = s.elements; } } else { cur = null; break; } } return cur != null && cur.hasNext(); } @Override public R next() throws E { if ((cur == null || !cur.hasNext()) && !hasNext()) { throw new NoSuchElementException(); } return cur.next(); } @Override public void close() throws E { if (s != null) { s.close(); } } }; final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); newCloseHandlers.add(newCloseHandler(iter)); if (N.notNullOrEmpty(closeHandlers)) { newCloseHandlers.addAll(closeHandlers); } return newStream(iter, newCloseHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flatmap(final Throwables.Function, ? extends E> mapper) { //NOSONAR assertNotClosed(); return newStream(new ExceptionalIterator() { private Collection c = null; private Iterator cur = null; @Override public boolean hasNext() throws E { while ((cur == null || !cur.hasNext()) && 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()) && !hasNext()) { throw new NoSuchElementException(); } return cur.next(); } }, closeHandlers); } /** * * @param * @param mapper * @return */ @IntermediateOp public ExceptionalStream flattMap(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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * @param * @param mapper * @return */ @Beta @IntermediateOp public ExceptionalStream flatMapp(final Throwables.Function, ? extends E> mapper) { assertNotClosed(); final ExceptionalIterator iter = new ExceptionalIterator<>() { private Stream s = null; private Iterator cur = null; @Override public boolean hasNext() throws E { while (cur == null || !cur.hasNext()) { if (elements.hasNext()) { if (s != null) { s.close(); s = null; } s = mapper.apply(elements.next()); if (s == null) { cur = null; } else { cur = s.iterator(); } } else { cur = null; break; } } return cur != null && cur.hasNext(); } @Override public R next() throws E { if ((cur == null || !cur.hasNext()) && !hasNext()) { throw new NoSuchElementException(); } return cur.next(); } @Override public void close() throws E { if (s != null) { s.close(); } } }; final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); newCloseHandlers.add(newCloseHandler(iter)); if (N.notNullOrEmpty(closeHandlers)) { newCloseHandlers.addAll(closeHandlers); } return newStream(iter, newCloseHandlers); } // /** // * // * @param // * @param mapper // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream flatMapByStream(final Throwables.Function, ? extends E> mapper) { // assertNotClosed(); // final ExceptionalIterator iter = new ExceptionalIterator() { // private Stream s = null; // private Iterator cur = null; // // @Override // public boolean hasNext() throws E { // while (cur == null || cur.hasNext() == false) { // if (elements.hasNext()) { // if (s != null) { // s.close(); // s = null; // } // // s = mapper.apply(elements.next()); // // if (s == null) { // cur = null; // } else { // cur = s.iterator(); // } // } 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 (s != null) { // s.close(); // } // } // }; // // final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); // // newCloseHandlers.add(newCloseHandler(iter)); // // if (N.notNullOrEmpty(closeHandlers)) { // newCloseHandlers.addAll(closeHandlers); // } // // return newStream(iter, newCloseHandlers); // } // // /** // * // * @param // * @param mapper // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream flatMapByStreamJdk( // final Throwables.Function, ? extends E> mapper) { // assertNotClosed(); // final ExceptionalIterator iter = new ExceptionalIterator() { // private java.util.stream.Stream s = null; // private Iterator cur = null; // // @Override // public boolean hasNext() throws E { // while (cur == null || cur.hasNext() == false) { // if (elements.hasNext()) { // if (s != null) { // s.close(); // s = null; // } // // s = mapper.apply(elements.next()); // // if (s == null) { // cur = null; // } else { // cur = s.iterator(); // } // } 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 (s != null) { // s.close(); // } // } // }; // // final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1); // // newCloseHandlers.add(newCloseHandler(iter)); // // if (N.notNullOrEmpty(closeHandlers)) { // newCloseHandlers.addAll(closeHandlers); // } // // return newStream(iter, newCloseHandlers); // } /** * * * @param * @param mapper * @return * @implNote same as ====> *
     * skipNulls().flatmap(mapper)
     * 
*/ @Beta @IntermediateOp public ExceptionalStream flatMapIfNotNull(final Throwables.Function, ? extends E> mapper) { return skipNulls().flatmap(mapper); } /** * * * @param * @param * @param mapper * @param mapper2 * @return * @implNote same as ====> *
     * skipNulls().flatmap(mapper).skipNulls().flatmap(mapper2)
     * 
*/ @Beta @IntermediateOp public ExceptionalStream flatMapIfNotNull(final Throwables.Function, ? extends E> mapper, final Throwables.Function, ? extends E> mapper2) { return skipNulls().flatmap(mapper).skipNulls().flatmap(mapper2); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } /** * * * @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()) { throw new NoSuchElementException(); } return cur[idx++]; } }, closeHandlers); } // /** // * // * @param mapper // * @return // */ // @IntermediateOp // public ExceptionalStream flatmapToInt(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 flatmapToLong(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 flatmapToDouble(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); // } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartial(final Throwables.Function, E> mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_IT).map(GET_AS_IT); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToInt(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_INT).map(GET_AS_INT); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToLong(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_LONG).map(GET_AS_LONG); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToDouble(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_DOUBLE).map(GET_AS_DOUBLE); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialJdk(final Throwables.Function, E> mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_IT_JDK).map(GET_AS_IT_JDK); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToIntJdk(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_INT_JDK).map(GET_AS_INT_JDK); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToLongJdk(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_LONG_JDK).map(GET_AS_LONG_JDK); } /** * Note: copied from StreamEx: https://github.com/amaembo/streamex * * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream mapPartialToDoubleJdk(final Throwables.Function mapper) { return map(mapper).filter((Throwables.Predicate) IS_PRESENT_DOUBLE_JDK).map(GET_AS_DOUBLE_JDK); } /** * * * @param * @param mapper * @return */ public ExceptionalStream mapMulti(final Throwables.BiConsumer, ? extends E> mapper) { final Deque queue = new ArrayDeque<>(); final Consumer consumer = queue::offer; final ExceptionalIterator iter = iteratorEx(); return newStream(new ExceptionalIterator() { @Override public boolean hasNext() throws E { if (queue.size() == 0) { while (iter.hasNext()) { mapper.accept(iter.next(), consumer); if (queue.size() > 0) { break; } } } return queue.size() > 0; } @Override public R next() throws E { if (queue.size() == 0 && !hasNext()) { throw new NoSuchElementException(); } return queue.poll(); } }, closeHandlers); } /** * * @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) NONE; private T prev = none; private T _1 = none; //NOSONAR @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()) { 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) NONE; private T prev = none; private T prev2 = none; private T _1 = none; //NOSONAR private T _2 = none; //NOSONAR @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()) { 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 */ @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 */ @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 */ @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 */ @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.groupTo(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 * @param * @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 collapsible test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @return */ @IntermediateOp public ExceptionalStream, E> collapse(final Throwables.BiPredicate collapsible) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator, E>() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public Stream next() throws E { final List c = new ArrayList<>(); c.add(hasNext ? next : (next = iter.next())); while ((hasNext = iter.hasNext())) { if (collapsible.test(next, (next = iter.next()))) { c.add(next); } else { break; } } return Stream.of(c); } }, closeHandlers); } /** * * @param * @param collapsible test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @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 { final C c = supplier.get(); c.add(hasNext ? next : (next = iter.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: *

     * 
     * ExceptionalStream.of(new Integer[0]).collapse((p, c) -> p < c, (r, c) -> r + c) => []
     * ExceptionalStream.of(1).collapse((p, c) -> p < c, (r, c) -> r + c) => [1]
     * ExceptionalStream.of(1, 2).collapse((p, c) -> p < c, (r, c) -> r + c) => [3]
     * ExceptionalStream.of(1, 2, 3).collapse((p, c) -> p < c, (r, c) -> r + c) => [6]
     * ExceptionalStream.of(1, 2, 3, 3, 2, 1).collapse((p, c) -> p < c, (r, c) -> r + c) => [6, 3, 2, 1]
     * 
     * 
* *
* This method only runs sequentially, even in parallel stream. * * @param collapsible test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @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 test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @param init is used by {@code op} to generate the first result value in the series. * @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 test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @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 test the current element with its previous element. The first parameter is the previous element of current element, the second parameter is the current element. * @param collector * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.BiPredicate collapsible, final Collector collector) { assertNotClosed(); final java.util.function.Supplier supplier = collector.supplier(); final java.util.function.BiConsumer accumulator = collector.accumulator(); final java.util.function.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 collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @return */ @IntermediateOp public ExceptionalStream, E> collapse(final Throwables.TriPredicate collapsible) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator, E>() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || iter.hasNext(); } @Override public Stream next() throws E { final T first = hasNext ? next : (next = iter.next()); final List c = new ArrayList<>(); c.add(first); while ((hasNext = iter.hasNext())) { if (collapsible.test(first, next, (next = iter.next()))) { c.add(next); } else { break; } } return Stream.of(c); } }, closeHandlers); } /** * * @param * @param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @param supplier * @return */ @IntermediateOp public > ExceptionalStream collapse(final Throwables.TriPredicate 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 { final T first = hasNext ? next : (next = iter.next()); final C c = supplier.get(); c.add(first); while ((hasNext = iter.hasNext())) { if (collapsible.test(first, 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((f, p, c) -> f < c, (r, c) -> r + c) => []
     * Stream.of(1).collapse((f, p, c) -> f < c, (r, c) -> r + c) => [1]
     * Stream.of(1, 2).collapse((f, p, c) -> f < c, (r, c) -> r + c) => [3]
     * Stream.of(1, 2, 3).collapse((f, p, c) -> f < c, (r, c) -> r + c) => [6]
     * Stream.of(1, 2, 3, 3, 2, 1).collapse((f, p, c) -> f < c, (r, c) -> r + c) => [11, 1]
     * 
     * 
* *
* This method only runs sequentially, even in parallel stream. * * @param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @param mergeFunction * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.TriPredicate 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 { final T first = hasNext ? next : (next = iter.next()); T res = first; while ((hasNext = iter.hasNext())) { if (collapsible.test(first, next, (next = iter.next()))) { res = mergeFunction.apply(res, next); } else { break; } } return res; } }, closeHandlers); } /** * * @param * @param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @param init is used by {@code op} to generate the first result value in the series. * @param op * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.TriPredicate 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 { final T first = hasNext ? next : (next = iter.next()); U res = op.apply(init, first); while ((hasNext = iter.hasNext())) { if (collapsible.test(first, next, (next = iter.next()))) { res = op.apply(res, next); } else { break; } } return res; } }, closeHandlers); } /** * * @param *@param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @param supplier * @param accumulator * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.TriPredicate 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 T first = hasNext ? next : (next = iter.next()); final R container = supplier.get(); accumulator.accept(container, first); while ((hasNext = iter.hasNext())) { if (collapsible.test(first, next, (next = iter.next()))) { accumulator.accept(container, next); } else { break; } } return container; } }, closeHandlers); } /** * Merge series of adjacent elements which satisfy the given predicate using * the merger function and return a new stream. * *

Example: *

     * 
     * ExceptionalStream.of(new Integer[0]).collapse((f, p, c) -> f < c, Collectors.summingInt(Fn.unboxI())) => []
     * ExceptionalStream.of(1).collapse((f, p, c) -> f < c, Collectors.summingInt(Fn.unboxI())) => [1]
     * ExceptionalStream.of(1, 2).collapse((f, p, c) -> f < c, Collectors.summingInt(Fn.unboxI())) => [3]
     * ExceptionalStream.of(1, 2, 3).collapse((f, p, c) -> f < c, Collectors.summingInt(Fn.unboxI())) => [6]
     * ExceptionalStream.of(1, 2, 3, 3, 2, 1).collapse((f, p, c) -> f < c, Collectors.summingInt(Fn.unboxI())) => [11, 1]
     * 
     * 
* * * @param * @param
* @param collapsible test the current element with the first element and previous element in the series. The first parameter is the first element of this series, the second parameter is the previous element and the third parameter is the current element. * @param collector * @return */ @IntermediateOp public ExceptionalStream collapse(final Throwables.TriPredicate collapsible, final Collector collector) { assertNotClosed(); final java.util.function.Supplier supplier = collector.supplier(); final java.util.function.BiConsumer accumulator = collector.accumulator(); final java.util.function.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 T first = hasNext ? next : (next = iter.next()); final A container = supplier.get(); accumulator.accept(container, first); while ((hasNext = iter.hasNext())) { if (collapsible.test(first, 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) { 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(value -> multiset.getAndRemove(value) > 0); } /** * * * @param * @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(value -> 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(value -> multiset.getAndRemove(value) < 1); } /** * * * @param * @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(value -> 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(value -> multiset.getAndRemove(value) < 1).append(ExceptionalStream. of(c).filter(value -> 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); } /** * * * @param a * @return */ @IntermediateOp @SafeVarargs public final ExceptionalStream prepend(final T... a) { return prepend(ExceptionalStream.of(a)); } /** * * * @param c * @return */ @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); } /** * * * @param a * @return */ @IntermediateOp @SafeVarargs public final ExceptionalStream append(final T... a) { return append(ExceptionalStream.of(a)); } /** * * * @param c * @return */ @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); } /** * * * @param a * @return */ @IntermediateOp @SafeVarargs public final ExceptionalStream appendIfEmpty(final T... a) { return appendIfEmpty(Arrays.asList(a)); } /** * * * @param c * @return */ @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.of(c.iterator()); } } } }, closeHandlers); } /** * Append if empty. * * @param supplier * @return */ @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(() -> close(holder)); } // @SuppressWarnings("rawtypes") // private static final Throwables.Predicate NOT_NULL_MASK = new Throwables.Predicate() { // @Override // public boolean test(final Object t) { // return t != NONE; // } // }; // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final T fallbackValue) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // // @Override // public boolean hasNext() throws E { // try { // return fallbackValueAvaiable && elements.hasNext(); // } catch (Exception e) { // return fallbackValueAvaiable; // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return elements.next(); // } catch (Exception e) { // fallbackValueAvaiable = false; // return fallbackValue; // } // } // }, false, null, closeHandlers); // } // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final Class type, final T fallbackValue) { // assertNotClosed(); // this.checkArgNotNull(type, "type"); // // return newStream(new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // // @Override // public boolean hasNext() throws E { // try { // return fallbackValueAvaiable && elements.hasNext(); // } catch (Exception e) { // if (ExceptionUtil.hasCause(e, type)) { // return fallbackValueAvaiable; // } else { // throw (E) e; // } // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return elements.next(); // } catch (Exception e) { // if (ExceptionUtil.hasCause(e, type)) { // fallbackValueAvaiable = false; // return fallbackValue; // } else { // throw (E) e; // } // } // } // }, false, null, closeHandlers); // } // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final Predicate predicate, final T fallbackValue) { // assertNotClosed(); // this.checkArgNotNull(predicate, "predicate"); // // return newStream(new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // // @Override // public boolean hasNext() throws E { // try { // return fallbackValueAvaiable && elements.hasNext(); // } catch (Exception e) { // if (predicate.test(e)) { // return fallbackValueAvaiable; // } else { // throw (E) e; // } // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return elements.next(); // } catch (Exception e) { // if (predicate.test(e)) { // fallbackValueAvaiable = false; // return fallbackValue; // } else { // throw (E) e; // } // } // } // }, false, null, closeHandlers); // } // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final Supplier> fallbackStreamSupplier) { // assertNotClosed(); // this.checkArgNotNull(fallbackStreamSupplier, "fallbackStreamSupplier"); // // final ExceptionalIterator iter = new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // private ExceptionalIterator iter = ExceptionalStream.this.elements; // private ExceptionalStream s = null; // // @Override // public boolean hasNext() throws E { // try { // return iter.hasNext(); // } catch (Exception e) { // if (fallbackValueAvaiable) { // useFallbackStream(fallbackStreamSupplier); // // return iter.hasNext(); // } else { // throw (E) e; // } // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return iter.next(); // } catch (Exception e) { // if (fallbackValueAvaiable) { // useFallbackStream(fallbackStreamSupplier); // // if (iter.hasNext()) { // return iter.next(); // } else { // return (T) NONE; // } // } else { // throw (E) e; // } // } // } // // @Override // public void close() { // if ((s != null && N.notNullOrEmpty(s.closeHandlers)) || N.notNullOrEmpty(ExceptionalStream.this.closeHandlers)) { // try { // if (s != null) { // s.close(); // } // } finally { // ExceptionalStream.this.close(); // } // } // } // // private void useFallbackStream(final Supplier> fallbackStream) { // fallbackValueAvaiable = false; // s = fallbackStream.get(); // iter = s.elements; // } // }; // // return newStream(iter).onClose(newCloseHandler(iter)).filter(NOT_NULL_MASK); // } // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final Class type, final Supplier> fallbackStreamSupplier) { // assertNotClosed(); // this.checkArgNotNull(type, "type"); // this.checkArgNotNull(fallbackStreamSupplier, "fallbackStreamSupplier"); // // final ExceptionalIterator iter = new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // private ExceptionalIterator iter = ExceptionalStream.this.elements; // private ExceptionalStream s = null; // // @Override // public boolean hasNext() throws E { // try { // return iter.hasNext(); // } catch (Exception e) { // if (fallbackValueAvaiable && ExceptionUtil.hasCause(e, type)) { // useFallbackStream(fallbackStreamSupplier); // // return iter.hasNext(); // } else { // throw (E) e; // } // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return iter.next(); // } catch (Exception e) { // if (fallbackValueAvaiable && ExceptionUtil.hasCause(e, type)) { // useFallbackStream(fallbackStreamSupplier); // // if (iter.hasNext()) { // return iter.next(); // } else { // return (T) NONE; // } // } else { // throw (E) e; // } // } // } // // @Override // public void close() { // if ((s != null && N.notNullOrEmpty(s.closeHandlers)) || N.notNullOrEmpty(ExceptionalStream.this.closeHandlers)) { // try { // if (s != null) { // s.close(); // } // } finally { // ExceptionalStream.this.close(); // } // } // } // // private void useFallbackStream(final Supplier> fallbackStream) { // fallbackValueAvaiable = false; // s = fallbackStream.get(); // iter = s.elements; // } // }; // // return newStream(iter).onClose(newCloseHandler(iter)).filter(NOT_NULL_MASK); // } // // @Beta // @IntermediateOp // public ExceptionalStream appendOnError(final Predicate predicate, final Supplier> fallbackStreamSupplier) { // assertNotClosed(); // this.checkArgNotNull(predicate, "predicate"); // this.checkArgNotNull(fallbackStreamSupplier, "fallbackStreamSupplier"); // // final ExceptionalIterator iter = new ExceptionalIterator() { // private boolean fallbackValueAvaiable = true; // private ExceptionalIterator iter = ExceptionalStream.this.elements; // private ExceptionalStream s = null; // // @Override // public boolean hasNext() throws E { // try { // return iter.hasNext(); // } catch (Exception e) { // if (fallbackValueAvaiable && predicate.test(e)) { // useFallbackStream(fallbackStreamSupplier); // // return iter.hasNext(); // } else { // throw (E) e; // } // } // } // // @Override // public T next() throws E { // if (hasNext() == false) { // throw new NoSuchElementException(); // } // // try { // return iter.next(); // } catch (Exception e) { // if (fallbackValueAvaiable && predicate.test(e)) { // useFallbackStream(fallbackStreamSupplier); // // if (iter.hasNext()) { // return iter.next(); // } else { // return (T) NONE; // } // } else { // throw (E) e; // } // } // } // // @Override // public void close() { // if ((s != null && N.notNullOrEmpty(s.closeHandlers)) || N.notNullOrEmpty(ExceptionalStream.this.closeHandlers)) { // try { // if (s != null) { // s.close(); // } // } finally { // ExceptionalStream.this.close(); // } // } // } // // private void useFallbackStream(final Supplier> fallbackStream) { // fallbackValueAvaiable = false; // s = fallbackStream.get(); // iter = s.elements; // } // }; // // return newStream(iter).onClose(newCloseHandler(iter)).filter(NOT_NULL_MASK); // } /** * * * @param exceptionSupplier * @return */ @IntermediateOp public ExceptionalStream throwIfEmpty(final Supplier exceptionSupplier) { this.checkArgNotNull(exceptionSupplier, "exceptionSupplier"); final Throwables.Supplier, E> tmp = () -> { throw exceptionSupplier.get(); }; return this.appendIfEmpty(tmp); } void close(Holder> holder) { if (holder.value() != null) { holder.value().close(); } } /** * * * @param * @param * @param func * @return * @throws E * @throws E2 */ @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(); } } /** * * * @param * @param action * @return * @throws E * @throws E2 */ @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); } /** * * * @param action * @return */ @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); } /** * * * @param action * @return */ @IntermediateOp public ExceptionalStream peekLast(final Throwables.Consumer action) { assertNotClosed(); return newStream(new ExceptionalIterator() { private boolean hasNext = false; private T next = null; @Override public boolean hasNext() throws E { return hasNext || elements.hasNext(); } @Override public T next() throws E { next = elements.next(); if (!(hasNext = elements.hasNext())) { action.accept(next); } return next; } }, sorted, cmp, closeHandlers); } /** * * @param predicate * @param action * @return */ @IntermediateOp public ExceptionalStream peekIf(final Throwables.Predicate predicate, final Throwables.Consumer action) { assertNotClosed(); checkArgNotNull(predicate, "predicate"); checkArgNotNull(action, "action"); return peek(it -> { if (predicate.test(it)) { action.accept(it); } }); } /** * * @param predicate The first parameter is the element. The second parameter is the count of iterated elements, starts with 1. * @param action * @return */ @Beta @IntermediateOp public ExceptionalStream peekIf(final Throwables.BiPredicate predicate, final Consumer action) { assertNotClosed(); checkArgNotNull(predicate, "predicate"); checkArgNotNull(action, "action"); final MutableLong count = MutableLong.of(0); return onEach(it -> { if (predicate.test(it, count.incrementAndGet())) { action.accept(it); } }); } /** * * @param chunkSize * @return */ @IntermediateOp public ExceptionalStream, E> split(final int chunkSize) { assertNotClosed(); return splitToList(chunkSize).map(Stream::of); } /** * 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()) { 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 java.util.function.Supplier supplier = collector.supplier(); final java.util.function.BiConsumer accumulator = collector.accumulator(); final java.util.function.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()) { 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); } /** * * * @param where * @return */ @IntermediateOp public ExceptionalStream, E> splitAt(final int where) { assertNotClosed(); checkArgNotNegative(where, "where"); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator, E>() { private int cursor = 0; @Override public boolean hasNext() throws E { return cursor < 2; } @Override public ExceptionalStream next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } ExceptionalStream result = null; if (cursor == 0) { final List list = new ArrayList<>(); int cnt = 0; while (cnt++ < where && iter.hasNext()) { list.add(iter.next()); } result = new ExceptionalStream<>(ExceptionalIterator.of(list.iterator()), sorted, cmp, null); } else { result = new ExceptionalStream<>(iter, sorted, cmp, null); } cursor++; return result; } @Override public long count() throws E { iter.count(); return 2 - cursor; //NOSONAR } @Override public void advance(long n) throws E { if (n == 0) { return; } else if (n == 1) { if (cursor == 0) { iter.advance(where); } else { iter.advance(Long.MAX_VALUE); } } else { iter.advance(Long.MAX_VALUE); } cursor = n >= 2 ? 2 : cursor + (int) n; } }, closeHandlers); } /** * * * @param where * @return */ @IntermediateOp public ExceptionalStream, E> splitAt(final Throwables.Predicate where) { assertNotClosed(); final ExceptionalIterator iter = elements; return newStream(new ExceptionalIterator, E>() { private int cursor = 0; private T next = null; private boolean hasNext = false; @Override public boolean hasNext() throws E { return cursor < 2; } @Override public ExceptionalStream next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } ExceptionalStream result = null; if (cursor == 0) { final List list = new ArrayList<>(); while (iter.hasNext()) { next = iter.next(); if (!where.test(next)) { list.add(next); } else { hasNext = true; break; } } result = new ExceptionalStream<>(ExceptionalIterator.of(list.iterator()), sorted, cmp, null); } else { ExceptionalIterator iterEx = iter; if (hasNext) { iterEx = new ExceptionalIterator<>() { private boolean isFirst = true; @Override public boolean hasNext() throws E { return isFirst || iter.hasNext(); } @Override public T next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } if (isFirst) { isFirst = false; return next; } else { return iter.next(); } } }; } result = new ExceptionalStream<>(iterEx, sorted, cmp, null); } cursor++; return result; } @Override public long count() throws E { iter.count(); return 2 - cursor; //NOSONAR } @Override public void advance(long n) throws E { if (n == 0) { return; } else if (n == 1) { if (cursor == 0) { while (iter.hasNext()) { next = iter.next(); if (!where.test(next)) { hasNext = true; break; } } } else { iter.advance(Long.MAX_VALUE); } } else { iter.advance(Long.MAX_VALUE); } cursor = n >= 2 ? 2 : cursor + (int) n; } }, closeHandlers); } /** * * @param windowSize * @param increment * @return */ @IntermediateOp public ExceptionalStream, E> sliding(final int windowSize, final int increment) { assertNotClosed(); return slidingToList(windowSize, increment).map(Stream::of); } /** * 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()) { 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(); result.addAll(queue); 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()); //NOSONAR 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 java.util.function.Supplier supplier = collector.supplier(); final java.util.function.BiConsumer accumulator = collector.accumulator(); final java.util.function.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()) { 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()); //NOSONAR 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"); if (n == 0) { return newStream(elements, sorted, cmp, closeHandlers); } return newStream(new ExceptionalIterator() { private boolean skipped = false; @Override public boolean hasNext() throws E { if (!skipped) { skipped = true; advance(n); } return elements.hasNext(); } @Override public T next() throws E { if (!skipped) { skipped = true; advance(n); } return elements.next(); } }, sorted, cmp, closeHandlers); } /** * * * @return * @deprecated Use {@link #skipNulls()} instead */ @Deprecated @IntermediateOp public ExceptionalStream skipNull() { return skipNulls(); } /** * * * @return */ @IntermediateOp public ExceptionalStream skipNulls() { 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); // } /** * * * @param n * @return */ @IntermediateOp public ExceptionalStream top(int n) { assertNotClosed(); return top(n, Comparators.NATURAL_ORDER); } /** * * * @param n * @param comparator * @return */ @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) { init(); } return cursor < to; } @Override public T next() throws E { if (!initialized) { init(); } if (cursor >= to) { throw new NoSuchElementException(); } return aar[cursor++]; } @Override public long count() throws E { if (!initialized) { init(); } return to - cursor; //NOSONAR } @Override public void advance(long n) throws E { if (!initialized) { 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) { 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); } /** * A queue with size up to n will be maintained to filter out the last n elements. * It may cause out of memory error if n is big enough. * *
* * All the elements will be loaded to get the last {@code n} elements and the Stream will be closed after that, if a terminal operation is triggered. * * @param n * @return * @see Stream#last(int) */ @Beta @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) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (!initialized) { init(); } return iter.next(); } private void init() throws E { if (!initialized) { 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); } /** * * * @param n * @return */ @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()) { throw new NoSuchElementException(); } deque.offerLast(elements.next()); return deque.pollFirst(); } }, sorted, cmp, closeHandlers); } /** * * * @return */ @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) { init(); } return cursor > 0; } @Override public T next() throws E { if (!initialized) { init(); } if (cursor <= 0) { throw new NoSuchElementException(); } return aar[--cursor]; } @Override public long count() throws E { if (!initialized) { init(); } return cursor; } @Override public void advance(long n) throws E { if (!initialized) { init(); } cursor = n < cursor ? cursor - (int) n : 0; } private void init() throws E { if (!initialized) { initialized = true; aar = (T[]) ExceptionalStream.this.toArrayForIntermediateOp(); cursor = aar.length; } } }, false, null, closeHandlers); } /** * * * @param distance * @return */ @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) { init(); } return cnt < len; } @Override public T next() throws E { if (!hasNext()) { throw new NoSuchElementException(); } return aar[(start + cnt++) % len]; } @Override public long count() throws E { if (!initialized) { init(); } return len - cnt; //NOSONAR } @Override public void advance(long n) throws E { if (!initialized) { init(); } cnt = n < len - cnt ? cnt + (int) n : len; } private void init() throws E { if (!initialized) { 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); } /** * * * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream shuffled() { return shuffled(RAND); } /** * * * @param rnd * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream shuffled(final Random rnd) { assertNotClosed(); return lazyLoad(a -> { N.shuffle(a, rnd); return a; }, false, null); } /** * * * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream sorted() { return sorted(Comparators.NATURAL_ORDER); } /** * * @param comparator * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream sorted(final Comparator comparator) { assertNotClosed(); final Comparator cmp = comparator == null ? Comparators.NATURAL_ORDER : comparator; //NOSONAR if (sorted && cmp == this.cmp) { return newStream(elements, sorted, comparator, closeHandlers); } return lazyLoad(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 = (o1, o2) -> N.compare(keyMapper.apply(o1), keyMapper.apply(o2)); return sorted(comparator); } /** * * * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream reverseSorted() { return sorted(Comparators.REVERSED_ORDER); } /** * * * @param comparator * @return */ @IntermediateOp @TerminalOpTriggered public ExceptionalStream reverseSorted(Comparator comparator) { final Comparator cmp = comparator == null ? Comparators.REVERSED_ORDER : comparator.reversed(); //NOSONAR return sorted(cmp); } /** * * @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) { init(); } return cursor < len; } @Override public T next() throws E { if (!initialized) { init(); } if (cursor >= len) { throw new NoSuchElementException(); } return aar[cursor++]; } @Override public long count() throws E { if (!initialized) { init(); } return len - cursor; //NOSONAR } @Override public void advance(long n) throws E { checkArgNotNegative(n, "n"); if (!initialized) { init(); } cursor = n > len - cursor ? len : cursor + (int) n; } private void init() throws E { if (!initialized) { initialized = true; aar = (T[]) op.apply(ExceptionalStream.this.toArrayForIntermediateOp()); len = aar.length; } } }, sorted, cmp, closeHandlers); } /** * * * @return */ @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) { 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) { initialized = true; iter = ExceptionalStream.this.iteratorEx(); list = new ArrayList<>(); } } }, false, null, closeHandlers); } /** * * * @param times * @return */ @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) { 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) { initialized = true; iter = ExceptionalStream.this.iteratorEx(); list = new ArrayList<>(); } } }, false, null, closeHandlers); } /** * * * @param permitsPerSecond * @return */ @IntermediateOp public ExceptionalStream rateLimited(double permitsPerSecond) { return rateLimited(RateLimiter.create(permitsPerSecond)); } /** * * * @param rateLimiter * @return * @see RateLimiter#create(double) */ @IntermediateOp public ExceptionalStream rateLimited(final RateLimiter rateLimiter) { assertNotClosed(); checkArgNotNull(rateLimiter, "rateLimiter"); final Throwables.Consumer action = it -> rateLimiter.acquire(); return onEach(action); } /** * * * @return */ @Beta @IntermediateOp public ExceptionalStream, E> timed() { return map(Timed::of); } /** * * * @param delimiter * @return */ @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()) { throw new NoSuchElementException(); } if (toInsert) { toInsert = false; return delimiter; } else { final T res = iter.next(); toInsert = true; return res; } } }, closeHandlers); } /** * * * @param step * @return */ @Beta @IntermediateOp public ExceptionalStream step(final long step) { assertNotClosed(); checkArgPositive(step, "step"); if (step == 1) { return skip(0); } final long skip = step - 1; final ExceptionalIterator iter = this.iteratorEx(); final ExceptionalIterator iterator = new ExceptionalIterator<>() { @Override public boolean hasNext() throws E { return iter.hasNext(); } @Override public T next() throws E { final T next = iter.next(); iter.advance(skip); return next; } }; return newStream(iterator, sorted, cmp, closeHandlers); } /** * * * @return */ @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 * @param b * @param c * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final Collection b, final Collection c, final Throwables.TriFunction zipFunction) { assertNotClosed(); return zip(this, ExceptionalStream.of(b), ExceptionalStream.of(c), zipFunction); } /** * * @param * @param * @param * @param b * @param c * @param valueForNoneA * @param valueForNoneB * @param valueForNoneC * @param zipFunction * @return */ @IntermediateOp public ExceptionalStream zipWith(final Collection b, final Collection c, final T valueForNoneA, final T2 valueForNoneB, final T3 valueForNoneC, final Throwables.TriFunction zipFunction) { assertNotClosed(); return zip(this, ExceptionalStream.of(b), ExceptionalStream.of(c), valueForNoneA, valueForNoneB, valueForNoneC, 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); } // // TODO First of all, it only works in sequential Stream, not parallel stream (and maybe not work in some other scenarios as well). // // Secondly, these onErrorXXX methods make it more difficult and complicated to use Stream. // // So, remove them. // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param errorConsumer // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorContinue(final Throwables.Consumer errorConsumer) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // while (true) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // // break; // } catch (Throwable e) { // logger.warn("ignoring error in onErrorContinue", e); // // errorConsumer.accept(e); // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, sorted, cmp, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param type // * @param errorConsumer // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorContinue(final Class type, // final Throwables.Consumer errorConsumer) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // while (true) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // // break; // } catch (Throwable e) { // if (type.isAssignableFrom(e.getClass())) { // logger.warn("ignoring error in onErrorContinue", e); // // errorConsumer.accept(e); // } else { // throwThrowable(e); // } // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, sorted, cmp, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param errorPredicate // * @param errorConsumer // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorContinue(final Throwables.Predicate errorPredicate, // final Throwables.Consumer errorConsumer) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // while (true) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // // break; // } catch (Throwable e) { // if (errorPredicate.test(e)) { // logger.warn("ignoring error in onErrorContinue", e); // // errorConsumer.accept(e); // } else { // throwThrowable(e); // } // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, sorted, cmp, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param errorPredicate // * @param errorConsumer // * @param maxErrorCountToStop // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorContinue(final Throwables.Predicate errorPredicate, // final Throwables.Consumer errorConsumer, final int maxErrorCountToStop) { // assertNotClosed(); // checkArgNotNegative(maxErrorCountToStop, "maxErrorCountToStop"); // // return newStream(new ExceptionalIterator() { // private final AtomicInteger errorCounter = new AtomicInteger(maxErrorCountToStop); // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // while (true) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // // break; // } catch (Throwable e) { // if (errorCounter.decrementAndGet() >= 0) { // if (errorPredicate.test(e)) { // logger.warn("ignoring error in onErrorContinue", e); // // errorConsumer.accept(e); // } else { // throwThrowable(e); // } // } else { // break; // } // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, sorted, cmp, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param fallbackValue // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorReturn(final T fallbackValue) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // logger.warn("ignoring error in onErrorReturn", e); // // next = fallbackValue; // } // } // // return next != none; // } // // @Override // public T next() { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param type // * @param fallbackValue // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorReturn(final Class type, final T fallbackValue) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // if (type.isAssignableFrom(e.getClass())) { // logger.warn("ignoring error in onErrorReturn", e); // // next = fallbackValue; // } else { // throwThrowable(e); // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param predicate // * @param fallbackValue // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorReturn(final Throwables.Predicate predicate, final T fallbackValue) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // if (predicate.test(e)) { // logger.warn("ignoring error in onErrorReturn", e); // // next = fallbackValue; // } else { // throwThrowable(e); // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param predicate // * @param supplierForFallbackValue // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorReturn(final Throwables.Predicate predicate, // final Throwables.Supplier supplierForFallbackValue) { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // if (predicate.test(e)) { // logger.warn("ignoring error in onErrorReturn", e); // // next = supplierForFallbackValue.get(); // } else { // throwThrowable(e); // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, closeHandlers); // } // // /** // * This method should be only applied sequential {@code Stream} and whose up-streams are sequential {@code Streams} as well. // * Because error happening in the operations executed by parallel stream will stop iteration on that {@Stream}, so the down-streams won't be able to continue. // * // * @param predicate // * @param mapperForFallbackValue // * @param maxErrorCountToStop // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream onErrorReturn(final Throwables.Predicate predicate, // final Throwables.Function mapperForFallbackValue, final int maxErrorCountToStop) { // assertNotClosed(); // checkArgNotNegative(maxErrorCountToStop, "maxErrorCountToStop"); // // return newStream(new ExceptionalIterator() { // private final AtomicInteger errorCounter = new AtomicInteger(maxErrorCountToStop); // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() throws E { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // if (errorCounter.decrementAndGet() >= 0) { // if (predicate.test(e)) { // logger.warn("ignoring error in onErrorReturn", e); // // next = mapperForFallbackValue.apply(e); // } else { // throwThrowable(e); // } // } else { // // break; // } // } // } // // return next != none; // } // // @Override // public T next() throws E { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, closeHandlers); // } // // @Beta // @IntermediateOp // public ExceptionalStream onErrorStop() { // assertNotClosed(); // // return newStream(new ExceptionalIterator() { // private final ExceptionalIterator iter = iteratorEx(); // private final T none = (T) NONE; // private T next = none; // private T ret = null; // // @Override // public boolean hasNext() { // if (next == none) { // try { // if (iter.hasNext()) { // next = iter.next(); // } // } catch (Throwable e) { // logger.warn("ignoring error in onErrorStop", e); // } // } // // return next != none; // } // // @Override // public T next() { // if (!hasNext()) { // throw new NoSuchElementException(); // } // // ret = next; // next = none; // return ret; // } // }, sorted, cmp, closeHandlers); // } // // private void throwThrowable(Throwable e) throws E { // if (e instanceof Error) { // throw (Error) e; // } else { // throw (E) e; // } // } // @Beta // @TerminalOp // public void foreach(java.util.function.Consumer action) throws E { // assertNotClosed(); // // forEach(Fnn.from(action)); // } /** * * @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(); } } /** * Iterate and execute {@code action} until the flag is set true. * Flag can only be set after at least one element is iterated and executed by {@code action}. * * @param * @param action the second parameter is a flag to break the for-each loop. * Set it to {@code true} to break the loop if you don't want to continue the {@code action}. * Iteration on this stream will also be stopped when this flag is set to {@code true}. * @throws E * @throws E2 * @see #forEachUntil(MutableBoolean, Throwables.Consumer) */ @Beta @TerminalOp public void forEachUntil(final Throwables.BiConsumer action) throws E, E2 { assertNotClosed(); final MutableBoolean flagToBreak = MutableBoolean.of(false); final Throwables.Consumer tmp = t -> action.accept(t, flagToBreak); takeWhile(value -> flagToBreak.isFalse()).forEach(tmp); } /** * Iterate and execute {@code action} until {@code flagToBreak} is set true. * If {@code flagToBreak} is set to true at the begin, there will be no element iterated from stream before this stream is stopped and closed. * * @param * @param flagToBreak a flag to break the for-each loop. * Set it to {@code true} to break the loop if you don't want to continue the {@code action}. * Iteration on this stream will also be stopped when this flag is set to {@code true}. * @param action * @throws E * @throws E2 * @see #forEachUntil(Throwables.BiConsumer) */ @Beta @TerminalOp public void forEachUntil(final MutableBoolean flagToBreak, final Throwables.Consumer action) throws E, E2 { assertNotClosed(); takeWhile(value -> 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) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } if (!elements.hasNext()) { 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) { int skipNum = increment - windowSize; while (skipNum-- > 0 && elements.hasNext()) { elements.next(); } if (!elements.hasNext()) { 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 * @param action * @param threadNum * @throws E the e * @throws E2 the e2 */ @Beta @TerminalOp public void forEachInParallel(Throwables.Consumer action, final int threadNum) throws E, E2 { assertNotClosed(); checkArgNotNull(action, "action"); try { unchecked().parallel(threadNum).forEach(action); } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } /** * * * @param * @param action * @param threadNum * @param executor * @throws E the e * @throws E2 the e2 */ @Beta @TerminalOp public void forEachInParallel(Throwables.Consumer action, final int threadNum, final Executor executor) throws E, E2 { assertNotClosed(); checkArgNotNull(action, "action"); try { unchecked().parallel(threadNum, executor).forEach(action); } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } /** * * @param comparator * @return * @throws E the e */ @TerminalOp public Optional min(Comparator comparator) throws E { assertNotClosed(); try { if (!elements.hasNext()) { 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()) { 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())) { 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()) && (++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 next = null; while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { return Optional.of(next); } } return Optional. empty(); } finally { close(); } } /** * Returns the first element matched by {@code predicateForFirst} if found or the first element if this stream is not empty * Otherwise an empty {@code Optional} will be returned. * * @param * @param predicateForFirst * @return * @throws E * @throws E2 */ @TerminalOp public Optional findFirstOrAny(final Throwables.Predicate predicateForFirst) throws E, E2 { assertNotClosed(); try { T ret = (T) NONE; T next = null; while (elements.hasNext()) { next = elements.next(); if (predicateForFirst.test(next)) { return Optional.of(next); } else if (ret == NONE) { ret = next; } } return ret == NONE ? Optional. empty() : Optional.of(ret); } finally { close(); } } /** * Returns the first element matched by {@code predicateForFirst} if found or the first element matched by {@code predicateForAny}. * Otherwise an empty {@code Optional} will be returned. * * @param * @param * @param predicateForFirst * @param predicateForAny * @return * @throws E * @throws E2 * @throws E3 */ @TerminalOp public Optional findFirstOrAny(final Throwables.Predicate predicateForFirst, final Throwables.Predicate predicateForAny) throws E, E2, E3 { assertNotClosed(); try { T ret = (T) NONE; T next = null; while (elements.hasNext()) { next = elements.next(); if (predicateForFirst.test(next)) { return Optional.of(next); } else if (ret == NONE && predicateForAny.test(next)) { ret = next; } } return ret == NONE ? Optional. empty() : Optional.of(ret); } finally { close(); } } /** * Returns the first element matched by {@code predicateForFirst} if found or the last element if this stream is not empty * Otherwise an empty {@code Optional} will be returned. * * @param * @param predicateForFirst * @return * @throws E * @throws E2 */ @TerminalOp public Optional findFirstOrLast(final Throwables.Predicate predicateForFirst) throws E, E2 { assertNotClosed(); try { T ret = (T) NONE; T next = null; while (elements.hasNext()) { next = elements.next(); if (predicateForFirst.test(next)) { return Optional.of(next); } else { ret = next; } } return ret == NONE ? Optional. empty() : Optional.of(ret); } finally { close(); } } /** * 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 { T result = (T) NONE; T next = null; while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { result = next; } } return result == NONE ? Optional. empty() : Optional.of(result); } finally { close(); } } /** * Same as {@code findFirst(Throwables.Predicate)}. * * @param * @param predicate * @return * @throws E * @throws E2 * @see #findFirst(Throwables.Predicate) */ @TerminalOp public Optional findAny(final Throwables.Predicate predicate) throws E, E2 { return findFirst(predicate); } /** * * * @param a * @return * @throws E */ @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(); } } /** * * * @param c * @return * @throws E */ @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(set::contains).distinct().limit(distinctCount).count() == distinctCount; } } finally { close(); } } /** * * * @param a * @return * @throws E */ @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(set::contains); } } finally { close(); } } /** * * * @param c * @return * @throws E */ @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(set::contains); } } finally { close(); } } /** * * * @return * @throws E */ @TerminalOp public boolean hasDuplicates() throws E { assertNotClosed(); try { final Set set = N.newHashSet(); while (elements.hasNext()) { if (!set.add(elements.next())) { return true; } } return false; } finally { close(); } } /** * * * @param k * @param comparator * @return * @throws E */ @TerminalOp public Optional kthLargest(int k, Comparator comparator) throws E { assertNotClosed(); checkArgPositive(k, "k"); try { if (!elements.hasNext()) { 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(); } } /** * * * @param comparator * @return * @throws E */ @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()) { 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()) { 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 */ @Beta @TerminalOp public Optional elementAt(final long position) throws E { assertNotClosed(); checkArgNotNegative(position, "position"); if (position == 0) { return first(); } else { return skip(position).first(); } } /** * * @return * @throws TooManyElementsException if there are more than one elements. * @throws E the e */ @TerminalOp public Optional onlyOne() throws TooManyElementsException, E { assertNotClosed(); try { Optional result = Optional.empty(); if (elements.hasNext()) { result = Optional.of(elements.next()); if (elements.hasNext()) { throw new TooManyElementsException("There are at least two elements: " + StringUtil.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 */ @SuppressWarnings("deprecation") @TerminalOp public ImmutableList toImmutableList() throws E { return ImmutableList.wrap(toList()); } /** * * @return * @throws E the e */ @SuppressWarnings("deprecation") @TerminalOp public ImmutableSet toImmutableSet() throws E { return ImmutableSet.wrap(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(); } } /** * * * @param * @param * @param func * @return * @throws E * @throws E2 */ @TerminalOp public R toListAndThen(Throwables.Function, R, E2> func) throws E, E2 { assertNotClosed(); return func.apply(toList()); } /** * * * @param * @param * @param func * @return * @throws E * @throws E2 */ @TerminalOp public R toSetAndThen(Throwables.Function, R, E2> func) throws E, E2 { assertNotClosed(); return func.apply(toSet()); } /** * * * @param * @param * @param * @param supplier * @param func * @return * @throws E * @throws E2 */ @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 * @param * @param keyMapper * @param valueMapper * @return * @throws E the e * @throws E2 * @throws E3 * @throws IllegalStateException if there are duplicated keys. * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @SuppressWarnings("deprecation") @TerminalOp public ImmutableMap toImmutableMap(final Throwables.Function keyMapper, final Throwables.Function valueMapper) throws E, E2, E3, IllegalStateException { return ImmutableMap.wrap(toMap(keyMapper, valueMapper)); } /** * * * @param the key type * @param the value type * @param * @param * @param * @param keyMapper * @param valueMapper * @param mergeFunction * @return * @throws E the e * @throws E2 * @throws E3 * @throws E4 * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @SuppressWarnings("deprecation") @TerminalOp public ImmutableMap toImmutableMap( final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Throwables.BinaryOperator mergeFunction) throws E, E2, E3, E4 { return ImmutableMap.wrap(toMap(keyMapper, valueMapper, mergeFunction)); } /** * * * @param the key type * @param the value type * @param * @param * @param keyMapper * @param valueMapper * @return * @throws E the e * @throws E2 * @throws E3 * @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 * @param * @param keyMapper * @param valueMapper * @param mapFactory * @return * @throws E the e * @throws E2 * @throws E3 * @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 * @param * @param * @param keyMapper * @param valueMapper * @param mergeFunction * @return * @throws E the e * @throws E2 * @throws E3 * @throws E4 * @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, E4 { return toMap(keyMapper, valueMapper, mergeFunction, Suppliers. ofMap()); } /** * * * @param the key type * @param the value type * @param * @param * @param * @param * @param keyMapper * @param valueMapper * @param mergeFunction * @param mapFactory * @return * @throws E the e * @throws E2 * @throws E3 * @throws E4 * @see {@link Fn.Fnn#throwingMerger()} * @see {@link Fn.Fnn#replacingMerger()} * @see {@link Fn.Fnn#ignoringMerger()} */ @TerminalOp public , E2 extends Exception, E3 extends Exception, E4 extends Exception> M toMap( final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Throwables.BinaryOperator mergeFunction, final Supplier mapFactory) throws E, E2, E3, E4 { 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(); merge(result, keyMapper.apply(next), valueMapper.apply(next), mergeFunction); } return result; } finally { close(); } } static void merge(Map map, K key, V value, Throwables.BinaryOperator remappingFunction) throws E { final V oldValue = map.get(key); if (oldValue == null && !map.containsKey(key)) { map.put(key, value); } else { map.put(key, remappingFunction.apply(oldValue, value)); } } // /** // * // * @param keyMapper // * @param downstream // * @return // * @see #groupTo(Throwables.Function, Collector) // * @deprecated replaced by {@code groupTo} // */ // @Deprecated // @TerminalOp // public final Map toMap(final Throwables.Function keyMapper, // final Collector downstream) throws E, E2 { // return groupTo(keyMapper, downstream); // } // // /** // * // * @param keyMapper // * @param downstream // * @param mapFactory // * @return // * @see #groupTo(Throwables.Function, Collector, Supplier) // * @deprecated replaced by {@code groupTo} // */ // @Deprecated // @TerminalOp // public final , E2 extends Exception> M toMap(final Throwables.Function keyMapper, // final Collector downstream, final Supplier mapFactory) throws E, E2 { // return groupTo(keyMapper, downstream, mapFactory); // } // // /** // * // * @param keyMapper // * @param valueMapper // * @param downstream // * @return // * @see #groupTo(Throwables.Function, Throwables.Function, Collector) // * @deprecated replaced by {@code groupTo} // */ // @Deprecated // @TerminalOp // public final Map toMap(final Throwables.Function keyMapper, // final Throwables.Function valueMapper, final Collector downstream) throws E, E2, E3 { // return groupTo(keyMapper, valueMapper, downstream); // } // // /** // * // * @param keyMapper // * @param valueMapper // * @param downstream // * @param mapFactory // * @return // * @see #groupTo(Throwables.Function, Throwables.Function, Collector, Supplier) // * @deprecated replaced by {@code groupTo} // */ // @Deprecated // @TerminalOp // public final , 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 { // return groupTo(keyMapper, valueMapper, downstream, mapFactory); // } /** * * * @param the key type * @param * @param keyMapper * @return * @throws E the e * @throws E2 * @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 * @param keyMapper * @param mapFactory * @return * @throws E the e * @throws E2 * @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 * @param * @param keyMapper * @param valueMapper * @return * @throws E the e * @throws E2 * @throws E3 */ @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 * @param * @param keyMapper * @param valueMapper * @param mapFactory * @return * @throws E the e * @throws E2 * @throws E3 * @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)) { result.put(key, new ArrayList<>()); } result.get(key).add(valueMapper.apply(next)); } return result; } finally { close(); } } /** * * * @param the key type * @param * @param * @param * @param keyMapper * @param downstream * @return * @throws E the e * @throws E2 */ @TerminalOp public Map groupTo(final Throwables.Function keyMapper, final Collector downstream) throws E, E2 { return groupTo(keyMapper, downstream, Suppliers. ofMap()); } /** * * * @param the key type * @param * @param * @param * @param * @param keyMapper * @param downstream * @param mapFactory * @return * @throws E the e * @throws E2 */ @TerminalOp public , E2 extends Exception> M groupTo(final Throwables.Function keyMapper, final Collector downstream, final Supplier mapFactory) throws E, E2 { return groupTo(keyMapper, Fnn. identity(), downstream, mapFactory); } /** * * * @param the key type * @param the value type * @param * @param * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @return * @throws E the e * @throws E2 * @throws E3 */ @TerminalOp public Map groupTo(final Throwables.Function keyMapper, final Throwables.Function valueMapper, final Collector downstream) throws E, E2, E3 { return groupTo(keyMapper, valueMapper, downstream, Suppliers. ofMap()); } /** * * * @param the key type * @param the value type * @param * @param * @param * @param * @param * @param keyMapper * @param valueMapper * @param downstream * @param mapFactory * @return * @throws E the e * @throws E2 * @throws E3 */ @TerminalOp public , E2 extends Exception, E3 extends Exception> M groupTo( 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 java.util.function.Supplier downstreamSupplier = downstream.supplier(); final java.util.function.BiConsumer downstreamAccumulator = downstream.accumulator(); final java.util.function.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 * @param predicate * @return * @throws E * @throws E2 * @see Collectors#partitioningBy(Predicate) */ @TerminalOp public Map> partitionTo(final Throwables.Predicate predicate) throws E, E2 { assertNotClosed(); return partitionTo(predicate, Collectors. toList()); } /** * * * @param * @param * @param * @param predicate * @param downstream * @return * @throws E * @throws E2 * @see Collectors#partitioningBy(Predicate, Collector) */ @TerminalOp public Map partitionTo(final Throwables.Predicate predicate, final Collector downstream) throws E, E2 { assertNotClosed(); final Throwables.Function keyMapper = t -> predicate.test(t); final Supplier> mapFactory = () -> N. newHashMap(2); final Map map = groupTo(keyMapper, downstream, mapFactory); if (!map.containsKey(Boolean.TRUE)) { map.put(Boolean.TRUE, downstream.finisher().apply(downstream.supplier().get())); } else if (!map.containsKey(Boolean.FALSE)) { map.put(Boolean.FALSE, downstream.finisher().apply(downstream.supplier().get())); } return map; } /** * * * @param * @param * @param keyMapper * @return * @throws E * @throws E2 */ @TerminalOp public ListMultimap toMultimap(final Throwables.Function keyMapper) throws E, E2 { return toMultimap(keyMapper, Suppliers. ofListMultimap()); } /** * * * @param * @param * @param * @param * @param keyMapper * @param mapFactory * @return * @throws E * @throws E2 */ @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); } /** * * * @param * @param * @param * @param * @param keyMapper * @param valueMapper * @return * @throws E * @throws E2 * @throws E3 */ @TerminalOp public ListMultimap toMultimap(final Throwables.Function keyMapper, final Throwables.Function valueMapper) throws E, E2, E3 { return toMultimap(keyMapper, valueMapper, Suppliers. ofListMultimap()); } /** * * * @param * @param * @param * @param * @param * @param * @param keyMapper * @param valueMapper * @param mapFactory * @return * @throws E * @throws E2 * @throws E3 */ @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(); } } /** * * * @return * @throws E */ @TerminalOp public Multiset toMultiset() throws E { return toMultiset(Suppliers. ofMultiset()); } /** * * * @param supplier * @return * @throws E */ @TerminalOp public Multiset toMultiset(Supplier> supplier) throws E { //NOSONAR assertNotClosed(); checkArgNotNull(supplier, "supplier"); try { final Multiset result = supplier.get(); while (elements.hasNext()) { result.add(elements.next()); } return result; } finally { close(); } } /** * * * @return * @throws E */ @TerminalOp public LongMultiset toLongMultiset() throws E { return toLongMultiset(Suppliers. ofLongMultiset()); } /** * * * @param supplier * @return * @throws E */ @TerminalOp public LongMultiset toLongMultiset(Supplier> supplier) throws E { //NOSONAR assertNotClosed(); checkArgNotNull(supplier, "supplier"); try { final LongMultiset 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 bean 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 bean 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 * @param func * @return * @throws E the e * @throws E2 */ @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 * @param func * @return * @throws E the e * @throws E2 */ @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 * @param func * @return * @throws E the e * @throws E2 */ @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 * @param func * @return * @throws E the e * @throws E2 */ @TerminalOp public OptionalDouble averageInt(Throwables.ToIntFunction func) throws E, E2 { assertNotClosed(); try { if (!elements.hasNext()) { return OptionalDouble.empty(); } long sum = 0; long count = 0; do { sum += func.applyAsInt(elements.next()); count++; } while (elements.hasNext()); return OptionalDouble.of(((double) sum) / count); } finally { close(); } } /** * * * @param * @param func * @return * @throws E the e * @throws E2 */ @TerminalOp public OptionalDouble averageLong(Throwables.ToLongFunction func) throws E, E2 { assertNotClosed(); try { if (!elements.hasNext()) { return OptionalDouble.empty(); } long sum = 0; long count = 0; do { sum += func.applyAsLong(elements.next()); count++; } while (elements.hasNext()); return OptionalDouble.of(((double) sum) / count); } finally { close(); } } /** * * * @param * @param func * @return * @throws E the e * @throws E2 */ @TerminalOp public OptionalDouble averageDouble(Throwables.ToDoubleFunction func) throws E, E2 { assertNotClosed(); try { if (!elements.hasNext()) { 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()) { 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 accumulator * @param conditionToBreak the input parameter is the return value of {@code accumulator}, not the element from this Stream. * Returns {@code true} to break the loop if you don't want to continue the {@code action}. * Iteration on this stream will also be stopped when this flag is set to {@code true}. * @return * @throws E * @throws E2 */ @Beta @TerminalOp public Optional reduceUntil(Throwables.BinaryOperator accumulator, Throwables.Predicate conditionToBreak) throws E, E2 { assertNotClosed(); checkArgNotNull(accumulator, "accumulator"); checkArgNotNull(conditionToBreak, "conditionToBreak"); final MutableBoolean flagToBreak = MutableBoolean.of(false); final Throwables.BinaryOperator newAccumulator = (t, u) -> { final T ret = accumulator.apply(t, u); if (flagToBreak.isFalse() && conditionToBreak.test(ret)) { flagToBreak.setValue(true); } return ret; }; return takeWhile(value -> flagToBreak.isFalse()).reduce(newAccumulator); } /** * * @param * @param * @param identity * @param accumulator * @param conditionToBreak the input parameter is the return value of {@code accumulator}, not the element from this Stream. * Returns {@code true} to break the loop if you don't want to continue the {@code action}. * Iteration on this stream will also be stopped when this flag is set to {@code true}. * @return * @throws E * @throws E2 */ @Beta @TerminalOp public U reduceUntil(final U identity, final Throwables.BiFunction accumulator, Throwables.Predicate conditionToBreak) throws E, E2 { assertNotClosed(); checkArgNotNull(accumulator, "accumulator"); checkArgNotNull(conditionToBreak, "conditionToBreak"); final MutableBoolean flagToBreak = MutableBoolean.of(false); final Throwables.BiFunction newAccumulator = (u, t) -> { final U ret = accumulator.apply(u, t); if (flagToBreak.isFalse() && conditionToBreak.test(ret)) { flagToBreak.setValue(true); } return ret; }; return takeWhile(value -> flagToBreak.isFalse()).reduce(identity, newAccumulator); } /** * * @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 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)); } /** * * * @param delimiter * @return * @throws E */ @TerminalOp public String join(final CharSequence delimiter) throws E { return join(delimiter, "", ""); } /** * * * @param delimiter * @param prefix * @param suffix * @return * @throws E */ @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 = N::stringOf; /** * * * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persist(final File file) throws E, IOException { return persist(TO_LINE_OF_STRING, file); } /** * * * @param header * @param tail * @param file * @return * @throws E * @throws IOException */ @TerminalOp 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 */ @TerminalOp public long persist(final Throwables.Function toLine, final File file) throws E, IOException { return persist(toLine, null, null, file); } /** * * * @param toLine * @param header * @param tail * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persist(final Throwables.Function toLine, final String header, final String tail, final File file) throws E, IOException { assertNotClosed(); final Writer writer = IOUtil.newFileWriter(file); try { return persist(toLine, header, tail, writer); } finally { IOUtil.close(writer); } } /** * * * @param toLine * @param os * @return * @throws E * @throws IOException */ @TerminalOp 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 */ @TerminalOp public long persist(Throwables.Function toLine, Writer writer) throws E, IOException { assertNotClosed(); return persist(toLine, null, null, writer); } /** * * * @param toLine * @param header * @param tail * @param writer * @return * @throws E * @throws IOException */ @TerminalOp 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); //NOSONAR 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(); } } /** * * * @param writeLine * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persist(final Throwables.BiConsumer writeLine, final File file) throws E, IOException { assertNotClosed(); return persist(writeLine, null, null, file); } /** * * * @param writeLine * @param header * @param tail * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persist(final Throwables.BiConsumer writeLine, final String header, final String tail, final File file) throws E, IOException { assertNotClosed(); final Writer writer = IOUtil.newFileWriter(file); try { return persist(writeLine, header, tail, writer); } finally { IOUtil.close(writer); } } /** * * * @param writeLine * @param writer * @return * @throws E * @throws IOException */ @TerminalOp public long persist(final Throwables.BiConsumer writeLine, final Writer writer) throws E, IOException { assertNotClosed(); return persist(writeLine, null, null, writer); } /** * * * @param writeLine * @param header * @param tail * @param writer * @return * @throws E * @throws IOException */ @TerminalOp 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); //NOSONAR 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(); } } /** * * * @param conn * @param insertSQL * @param batchSize * @param batchIntervalInMillis * @param stmtSetter * @return * @throws E * @throws SQLException */ @TerminalOp public long persist(final Connection conn, final String insertSQL, final int batchSize, final long batchIntervalInMillis, final Throwables.BiConsumer stmtSetter) throws E, SQLException { assertNotClosed(); PreparedStatement stmt = null; try { stmt = conn.prepareStatement(insertSQL); return persist(stmt, batchSize, batchIntervalInMillis, stmtSetter); } finally { IOUtil.closeQuietly(stmt); } } /** * * * @param stmt * @param batchSize * @param batchIntervalInMillis * @param stmtSetter * @return * @throws E * @throws SQLException */ @TerminalOp public long persist(final PreparedStatement stmt, final int batchSize, final long batchIntervalInMillis, final Throwables.BiConsumer stmtSetter) throws E, SQLException { assertNotClosed(); checkArgument(batchSize > 0 && batchIntervalInMillis >= 0, "'batchSize'=%s must be greater than 0 and 'batchIntervalInMillis'=%s can't be negative", batchSize, batchIntervalInMillis); 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 (batchIntervalInMillis > 0) { N.sleep(batchIntervalInMillis); } } } 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); } } } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(File file) throws E, IOException { final Writer writer = IOUtil.newFileWriter(file); try { return persistToCSV(writer); } finally { IOUtil.close(writer); } } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param csvHeaders * @param file * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(Collection csvHeaders, File file) throws E, IOException { final Writer writer = IOUtil.newFileWriter(file); try { return persistToCSV(csvHeaders, writer); } finally { IOUtil.close(writer); } } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param os * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(OutputStream os) throws E, IOException { final BufferedWriter bw = Objectory.createBufferedWriter(os); try { return persistToCSV(bw); } finally { IOUtil.close(bw); } } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param csvHeaders * @param os * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(Collection csvHeaders, OutputStream os) throws E, IOException { final BufferedWriter bw = Objectory.createBufferedWriter(os); try { return persistToCSV(csvHeaders, bw); } finally { IOUtil.close(bw); } } private static final Throwables.TriConsumer, Object, BufferedJSONWriter, IOException> WRITE_CSV_ELEMENT_WITH_TYPE; private static final Throwables.BiConsumer WRITE_CSV_ELEMENT; private static final Throwables.BiConsumer WRITE_CSV_STRING; static { final JSONParser jsonParser = ParserFactory.createJSONParser(); final Type strType = N.typeOf(String.class); final JSONSerializationConfig config = JSC.create(); config.setDateTimeFormat(DateTimeFormat.ISO_8601_TIMESTAMP); config.quoteMapKey(true); config.quotePropName(true); WRITE_CSV_ELEMENT_WITH_TYPE = (type, element, bw) -> { if (element == null) { bw.write(Strings.NULL_CHAR_ARRAY); } else { if (type.isSerializable()) { type.writeCharacter(bw, element, config); } else { strType.writeCharacter(bw, jsonParser.serialize(element, config), config); } } }; WRITE_CSV_ELEMENT = (element, bw) -> { if (element == null) { bw.write(Strings.NULL_CHAR_ARRAY); } else { WRITE_CSV_ELEMENT_WITH_TYPE.accept(N.typeOf(element.getClass()), element, bw); } }; WRITE_CSV_STRING = (str, bw) -> strType.writeCharacter(bw, str, config); } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param writer * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(Writer writer) throws E, IOException { assertNotClosed(); try { final boolean isBufferedWriter = writer instanceof BufferedJSONWriter; final BufferedJSONWriter bw = isBufferedWriter ? (BufferedJSONWriter) writer : Objectory.createBufferedJSONWriter(writer); final ExceptionalIterator iter = iteratorEx(); long cnt = 0; T next = null; Class cls = null; try { if (iter.hasNext()) { next = iter.next(); cnt++; cls = next.getClass(); if (ClassUtil.isBeanClass(cls)) { final List propInfoList = ParserUtil.getBeanInfo(cls).propInfoList; final int headerSize = propInfoList.size(); PropInfo propInfo = null; for (int i = 0; i < headerSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_STRING.accept(propInfoList.get(i).name, bw); } bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headerSize; i++) { propInfo = propInfoList.get(i); if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT_WITH_TYPE.accept(propInfo.jsonXmlType, propInfo.getPropValue(next), bw); } while (iter.hasNext()) { next = iter.next(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headerSize; i++) { propInfo = propInfoList.get(i); if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT_WITH_TYPE.accept(propInfo.jsonXmlType, propInfo.getPropValue(next), bw); } } } else if (next instanceof Map) { Map row = (Map) next; final List keys = new ArrayList<>(row.keySet()); final int headerSize = keys.size(); for (int i = 0; i < headerSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(keys.get(i), bw); } bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headerSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row.get(keys.get(i)), bw); } while (iter.hasNext()) { row = (Map) iter.next(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headerSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row.get(keys.get(i)), bw); } } } else { throw new RuntimeException(cls + " is no supported for CSV format. Only bean/Map are supported"); } } bw.flush(); } finally { if (!isBufferedWriter) { Objectory.recycle((BufferedWriter) bw); } } return cnt; } finally { close(); } } /** * Each line in the output file/Writer is an array of JSON String without root bracket. * * @param csvHeaders * @param writer * @return * @throws E * @throws IOException */ @TerminalOp public long persistToCSV(Collection csvHeaders, Writer writer) throws E, IOException { checkArgNotNullOrEmpty(csvHeaders, "csvHeaders"); assertNotClosed(); try { List headers = new ArrayList<>(csvHeaders); final boolean isBufferedWriter = writer instanceof BufferedJSONWriter; final BufferedJSONWriter bw = isBufferedWriter ? (BufferedJSONWriter) writer : Objectory.createBufferedJSONWriter(writer); final int headSize = headers.size(); final ExceptionalIterator iter = iteratorEx(); long cnt = 0; T next = null; Class cls = null; try { if (iter.hasNext()) { next = iter.next(); cnt++; cls = next.getClass(); if (ClassUtil.isBeanClass(cls)) { final BeanInfo beanInfo = ParserUtil.getBeanInfo(cls); final PropInfo[] propInfos = new PropInfo[headSize]; PropInfo propInfo = null; for (int i = 0; i < headSize; i++) { propInfos[i] = beanInfo.getPropInfo(headers.get(i)); } for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_STRING.accept(headers.get(i), bw); } bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { propInfo = propInfos[i]; if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT_WITH_TYPE.accept(propInfo.jsonXmlType, propInfo.getPropValue(next), bw); } while (iter.hasNext()) { next = iter.next(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { propInfo = propInfos[i]; if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT_WITH_TYPE.accept(propInfo.jsonXmlType, propInfo.getPropValue(next), bw); } } } else if (next instanceof Map) { Map row = (Map) next; for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_STRING.accept(headers.get(i), bw); } bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row.get(headers.get(i)), bw); } while (iter.hasNext()) { row = (Map) iter.next(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row.get(headers.get(i)), bw); } } } else if (next instanceof Collection) { Collection row = (Collection) next; for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_STRING.accept(headers.get(i), bw); } bw.write(IOUtil.LINE_SEPARATOR); Iterator rowIter = row.iterator(); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(rowIter.next(), bw); } while (iter.hasNext()) { row = (Collection) iter.next(); rowIter = row.iterator(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(rowIter.next(), bw); } } } else if (next instanceof Object[]) { Object[] row = (Object[]) next; for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_STRING.accept(headers.get(i), bw); } bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row[i], bw); } while (iter.hasNext()) { row = (Object[]) iter.next(); cnt++; bw.write(IOUtil.LINE_SEPARATOR); for (int i = 0; i < headSize; i++) { if (i > 0) { bw.write(Strings.ELEMENT_SEPARATOR_CHAR_ARRAY); } WRITE_CSV_ELEMENT.accept(row[i], bw); } } } else { throw new RuntimeException(cls + " is no supported for CSV format. Only bean/Map are supported"); } } bw.flush(); } finally { if (!isBufferedWriter) { Objectory.recycle((BufferedWriter) bw); } } return cnt; } finally { close(); } } /** * * * @throws E */ @Beta @TerminalOp public void println() throws E { N.println(join(", ", "[", "]")); } /** * * * @return */ @IntermediateOp public Stream unchecked() { assertNotClosed(); if (N.isNullOrEmpty(this.closeHandlers)) { return Stream.of(newObjIteratorEx(elements)); } else { return Stream.of(newObjIteratorEx(elements)).onClose(() -> { try { ExceptionalStream.this.close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } }); } } /** * * * @return */ @IntermediateOp public java.util.stream.Stream toJdkStream() { assertNotClosed(); final Spliterator spliterator = Spliterators.spliteratorUnknownSize(newObjIteratorEx(elements), Spliterator.ORDERED | Spliterator.IMMUTABLE); if (isEmptyCloseHandlers(closeHandlers)) { return StreamSupport.stream(spliterator, false); } else { return StreamSupport.stream(spliterator, false).onClose(() -> { try { ExceptionalStream.this.close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } }); } } // public ExceptionalStream __(final Class targetExceptionType) { // checkArgNotNull(targetExceptionType, "targetExceptionType"); // // final Constructor msgCauseConstructor = ClassUtil.getDeclaredConstructor(targetExceptionType, String.class, Throwable.class); // final Constructor causeOnlyConstructor = ClassUtil.getDeclaredConstructor(targetExceptionType, Throwable.class); // // checkArgument(msgCauseConstructor != null || causeOnlyConstructor != null, // "No constructor found with parameters: (String.class, Throwable.class), or (Throwable.class)"); // // final Function convertE = msgCauseConstructor != null ? new Function() { // @Override // public E2 apply(Exception e) { // return ClassUtil.invokeConstructor(msgCauseConstructor, e.getMessage(), e); // } // } : new Function() { // @Override // public E2 apply(Exception e) { // return ClassUtil.invokeConstructor(causeOnlyConstructor, e); // } // }; // // Deque> newCloseHandlers = null; // // if (closeHandlers != null) { // newCloseHandlers = new ArrayDeque<>(1); // newCloseHandlers.add(new Throwables.Runnable() { // @Override // public void run() throws E2 { // try { // close(); // } catch (Exception e) { // throw convertE.apply(e); // } // } // }); // } // // return newStream(new ExceptionalIterator() { // private ExceptionalIterator iter = null; // private boolean initialized = false; // // @Override // public boolean hasNext() throws E2 { // if (initialized == false) { // init(); // } // // try { // return iter.hasNext(); // } catch (Exception e) { // throw convertE.apply(e); // } // } // // @Override // public T next() throws E2 { // if (initialized == false) { // init(); // } // // try { // return iter.next(); // } catch (Exception e) { // throw convertE.apply(e); // } // } // // @Override // public void skip(long n) throws E2 { // checkArgNotNegative(n, "n"); // // if (initialized == false) { // init(); // } // // try { // iter.skip(n); // } catch (Exception e) { // throw convertE.apply(e); // } // } // // @Override // public long count() throws E2 { // if (initialized == false) { // init(); // } // // try { // return iter.count(); // } catch (Exception e) { // throw convertE.apply(e); // } // } // // private void init() { // if (initialized == false) { // initialized = true; // // iter = ExceptionalStream.this.elements; // // } // } // }, sorted, comparator, newCloseHandlers); // } /** * * * @return */ @Beta @IntermediateOp public ExceptionalStream cast() { assertNotClosed(); return (ExceptionalStream) this; } /** * * * @param * @param * @param transfer * @return */ @Beta @IntermediateOp public ExceptionalStream __(Function, ExceptionalStream> transfer) { //NOSONAR assertNotClosed(); checkArgNotNull(transfer, "transfer"); return transfer.apply(this); } // /** // * // * @param // * @param // * @param terminalOp should be terminal operation. // * @param mapper // * @return // */ // @TerminalOp // @Beta // public R __(final Function, U> terminalOp, final Throwables.Function mapper) throws E { // return mapper.apply(terminalOp.apply(this)); // } // // /** // * // * @param // * @param terminalOp should be terminal operation. // * @param action // * @return // */ // @TerminalOp // @Beta // public R __(final Function, R> terminalOp, final Throwables.Consumer action) throws E { // final R result = terminalOp.apply(this); // action.accept(result); // return result; // } /** * Temporarily switch the stream to parallel stream for operation {@code ops} and then switch back to sequence stream. *
* * * @param * @param ops * @return * @see Stream#sps(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream sps(final Function, ? extends Stream> ops) { assertNotClosed(); return checked(((Stream) ops.apply(this.unchecked().parallel())), true); } /** * Temporarily switch the stream to parallel stream for operation {@code ops} and then switch back to sequence stream. *
* * * @param * @param maxThreadNum * @param ops * @return * @see Stream#sps(int, Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream sps(final int maxThreadNum, final Function, ? extends Stream> ops) { assertNotClosed(); return checked(((Stream) ops.apply(this.unchecked().parallel(maxThreadNum))), true); } // /** // * // * @param // * @param maxThreadNum // * @param withVirtualThread // * @param ops // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream sps(final int maxThreadNum, final boolean withVirtualThread, // final Function, ? extends Stream> ops) { // assertNotClosed(); // // return checked(((Stream) ops.apply(this.unchecked().parallel(maxThreadNum, withVirtualThread))), true); // } // // /** // * // * @param // * @param maxThreadNum // * @param executorNumForVirtualThread // * @param ops // * @return // */ // @Beta // @IntermediateOp // public ExceptionalStream sps(final int maxThreadNum, final int executorNumForVirtualThread, // final Function, ? extends Stream> ops) { // assertNotClosed(); // // return checked(((Stream) ops.apply(this.unchecked().parallel(maxThreadNum, executorNumForVirtualThread))), true); // } /** * Temporarily switch the stream to parallel stream for operation {@code filter} and then switch back to sequence stream. *
* * * @param predicate * @return * @see Stream#spsFilter(Predicate) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFilter(final Throwables.Predicate predicate) { final Function, Stream> ops = s -> s.filter(Fn.pp(predicate)); return sps(ops); } /** * Temporarily switch the stream to parallel stream for operation {@code map} and then switch back to sequence stream. *
* * * @param * @param mapper * @return * @see Stream#spsMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsMap(final Throwables.Function mapper) { final Function, Stream> ops = s -> s.map(Fn.ff(mapper)); return sps(ops); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param mapper * @return * @see Stream#spsFlatMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatMap(final Throwables.Function, E> mapper) { final Function, Stream> ops = s -> s.flatMap(Fn.ff(mapper)); return sps(ops); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param mapper * @return * @see Stream#spsFlatmap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatmap(final Throwables.Function, E> mapper) { //NOSONAR final Function, Stream> ops = s -> s.flatmap(Fn.ff(mapper)); return sps(ops); } /** * Temporarily switch the stream to parallel stream for operation {@code onEach} and then switch back to sequence stream. *
* * * @param action * @return * @see Stream#onEach(Consumer) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsOnEach(final Throwables.Consumer action) { final Function, Stream> ops = s -> s.onEach(Fn.cc(action)); return sps(ops); } /** * Temporarily switch the stream to parallel stream for operation {@code filter} and then switch back to sequence stream. *
* * @param maxThreadNum * @param predicate * @return * @see Stream#spsFilter(int, Predicate) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFilter(final int maxThreadNum, final Throwables.Predicate predicate) { final Function, Stream> ops = s -> s.filter(Fn.pp(predicate)); return sps(maxThreadNum, ops); } /** * Temporarily switch the stream to parallel stream for operation {@code map} and then switch back to sequence stream. *
* * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsMap(int, Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsMap(final int maxThreadNum, final Throwables.Function mapper) { final Function, Stream> ops = s -> s.map(Fn.ff(mapper)); return sps(maxThreadNum, ops); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsFlatMap(int, Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatMap(final int maxThreadNum, final Throwables.Function, E> mapper) { //NOSONAR final Function, Stream> ops = s -> s.flatMap(Fn.ff(mapper)); return sps(maxThreadNum, ops); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsFlatmap(int, Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatmap(final int maxThreadNum, final Throwables.Function, E> mapper) { //NOSONAR final Function, Stream> ops = s -> s.flatmap(Fn.ff(mapper)); return sps(maxThreadNum, ops); } /** * Temporarily switch the stream to parallel stream for operation {@code onEach} and then switch back to sequence stream. *
* * @param maxThreadNum * @param action * @return * @see Stream#onEach(int, Consumer) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsOnEach(final int maxThreadNum, final Throwables.Consumer action) { final Function, Stream> ops = s -> s.onEach(Fn.cc(action)); return sps(maxThreadNum, ops); } /** * Temporarily switch the stream to parallel stream for operation {@code filter} and then switch back to sequence stream. *
* * * @param predicate * @return * @see Stream#spsFilter(Predicate) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFilterE(final Throwables.Predicate predicate) { return checked(unchecked().spsFilterE(predicate), true); } /** * Temporarily switch the stream to parallel stream for operation {@code map} and then switch back to sequence stream. *
* * @param * @param mapper * @return * @see Stream#spsMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsMapE(final Throwables.Function mapper) { return checked(unchecked(). spsMapE(mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param mapper * @return * @see Stream#spsFlatMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatMapE(final Throwables.Function, ? extends Exception> mapper) { return checked(unchecked(). spsFlatMapE(mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param mapper * @return * @see Stream#spsFlatmap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatmapE( //NOSONAR final Throwables.Function, ? extends Exception> mapper) { return checked(unchecked(). spsFlatmapE(mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code onEach} and then switch back to sequence stream. *
* * * @param action * @return * @see Stream#onEach(Consumer) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsOnEachE(final Throwables.Consumer action) { return checked(unchecked().spsOnEachE(action), true); } /** * Temporarily switch the stream to parallel stream for operation {@code filter} and then switch back to sequence stream. *
* * * @param maxThreadNum * @param predicate * @return * @see Stream#spsFilter(Predicate) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFilterE(final int maxThreadNum, final Throwables.Predicate predicate) { return checked(unchecked().spsFilterE(maxThreadNum, predicate), true); } /** * Temporarily switch the stream to parallel stream for operation {@code map} and then switch back to sequence stream. *
* * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsMapE(final int maxThreadNum, final Throwables.Function mapper) { return checked(unchecked(). spsMapE(maxThreadNum, mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsFlatMap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatMapE(final int maxThreadNum, //NOSONAR final Throwables.Function, ? extends Exception> mapper) { return checked(unchecked(). spsFlatMapE(maxThreadNum, mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code flatMap} and then switch back to sequence stream. *
* * * @param * @param maxThreadNum * @param mapper * @return * @see Stream#spsFlatmap(Function) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsFlatmapE(final int maxThreadNum, //NOSONAR final Throwables.Function, ? extends Exception> mapper) { return checked(unchecked(). spsFlatmapE(maxThreadNum, mapper), true); } /** * Temporarily switch the stream to parallel stream for operation {@code onEach} and then switch back to sequence stream. *
* * * @param maxThreadNum * @param action * @return * @see Stream#onEach(Consumer) * @see ExceptionUtil#toRuntimeException(Throwable) * @see ExceptionUtil#registerRuntimeExceptionMapper(Class, Function) * @see ExceptionUtil#hasCause(Throwable, Class) * @see ExceptionUtil#hasCause(Throwable, Predicate) */ @Beta @IntermediateOp public ExceptionalStream spsOnEachE(final int maxThreadNum, final Throwables.Consumer action) { return checked(unchecked().spsOnEachE(maxThreadNum, action), true); } static ExceptionalStream checked(final Stream stream, final boolean isForSps) { if (stream == null) { return empty(); } ExceptionalIterator iter = null; if (isForSps) { iter = new ExceptionalIterator<>() { private Stream s = stream; private Iterator iter = null; private boolean isInitialized = false; @Override public boolean hasNext() throws E { try { if (!isInitialized) { init(); } return iter.hasNext(); } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } @Override public T next() throws E { try { if (!isInitialized) { init(); } return iter.next(); } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } @Override public void advance(long n) throws E { try { if (iter == null) { s = s.skip(n); } else { super.advance(n); } } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } @Override public long count() throws E { try { if (iter == null) { return s.count(); } else { return super.count(); } } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } @Override public void close() throws E { try { s.close(); } catch (Exception e) { throw (E) ExceptionUtil.tryToGetOriginalCheckedException(e); } } private void init() { if (!isInitialized) { isInitialized = true; iter = s.iterator(); } } }; } else { iter = new ExceptionalIterator<>() { private Stream s = stream; private Iterator iter = null; private boolean isInitialized = false; @Override public boolean hasNext() throws E { if (!isInitialized) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (!isInitialized) { init(); } return iter.next(); } @Override public void advance(long n) throws E { if (iter == null) { s = s.skip(n); } else { super.advance(n); } } @Override public long count() throws E { if (iter == null) { return s.count(); } else { return super.count(); } } @Override public void close() throws E { s.close(); } private void init() { if (!isInitialized) { isInitialized = true; iter = stream.iterator(); } } }; } final ExceptionalIterator tmp = iter; return newStream(tmp).onClose(newCloseHandler(tmp)); } /** * * @param predicate * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp 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) { while (elements.hasNext()) { next = elements.next(); if (predicate.test(next)) { hasNext = true; break; } } } return hasNext; } @Override public T next() throws Exception { if (!hasNext && !hasNext()) { throw new NoSuchElementException(); } hasNext = false; return next; } }, sorted, cmp, (Deque) closeHandlers); } /** * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp 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 */ @Beta @IntermediateOp 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()) { 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()) && !hasNext()) { 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(newCloseHandler(iter)); if (N.notNullOrEmpty(closeHandlers)) { newCloseHandlers.addAll(closeHandlers); } return newStream(iter, newCloseHandlers); } /** * * @param * @param mapper * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp public ExceptionalStream flatmapE(final Throwables.Function, ? extends Exception> mapper) { //NOSONAR assertNotClosed(); return newStream(new ExceptionalIterator() { private Iterator cur = null; private Collection c = null; @Override public boolean hasNext() throws Exception { while ((cur == null || !cur.hasNext()) && 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()) && !hasNext()) { throw new NoSuchElementException(); } return cur.next(); } }, (Deque) closeHandlers); } /** * * @param action * @return */ @SuppressWarnings("rawtypes") @Beta @IntermediateOp 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 terminalAction a terminal operation should be called. * @return */ @Beta @TerminalOp public ContinuableFuture asyncRun(final Throwables.Consumer, ? extends Exception> terminalAction) { assertNotClosed(); checkArgNotNull(terminalAction, "terminalAction"); return ContinuableFuture.run(() -> terminalAction.accept(ExceptionalStream.this)); } /** * * @param terminalAction a terminal operation should be called. * @param executor * @return */ @Beta @TerminalOp public ContinuableFuture asyncRun(final Throwables.Consumer, ? extends Exception> terminalAction, final Executor executor) { assertNotClosed(); checkArgNotNull(terminalAction, "terminalAction"); checkArgNotNull(executor, "executor"); return ContinuableFuture.run(() -> terminalAction.accept(ExceptionalStream.this), executor); } /** * * @param * @param terminalAction a terminal operation should be called. * @return */ @Beta @TerminalOp public ContinuableFuture asyncCall(final Throwables.Function, R, ? extends Exception> terminalAction) { assertNotClosed(); checkArgNotNull(terminalAction, "terminalAction"); return ContinuableFuture.call(() -> terminalAction.apply(ExceptionalStream.this)); } /** * * @param * @param terminalAction a terminal operation should be called. * @param executor * @return */ @Beta @TerminalOp public ContinuableFuture asyncCall(final Throwables.Function, R, ? extends Exception> terminalAction, final Executor executor) { assertNotClosed(); checkArgNotNull(terminalAction, "terminalAction"); checkArgNotNull(executor, "executor"); return ContinuableFuture.call(() -> terminalAction.apply(ExceptionalStream.this), executor); } /** * * @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); } /** * It will be called by terminal operations in final. */ @TerminalOp @Override public synchronized void close() { if (isClosed) { return; } if (isEmptyCloseHandlers(closeHandlers)) { if (N.notNullOrEmpty(closeHandlers)) { closeHandlers.clear(); } isClosed = true; return; } // // Only mark the stream closed if closeHandlers are not empty. // if (isClosed || isEmptyCloseHandlers(closeHandlers)) { // return; // } isClosed = true; logger.debug("Closing ExceptionalStream"); close(closeHandlers); if (N.notNullOrEmpty(closeHandlers)) { closeHandlers.clear(); } } static boolean isEmptyCloseHandlers(final Collection> closeHandlers) { return N.isNullOrEmpty(closeHandlers) || (closeHandlers.size() == 1 && N.firstOrNullIfEmpty(closeHandlers) == EMPTY_CLOSE_HANDLER); } @SuppressWarnings("rawtypes") private static final Throwables.Runnable EMPTY_CLOSE_HANDLER = () -> { // do nothing. }; private static Throwables.Runnable newCloseHandler(final ExceptionalIterator iter) { if (iter == null) { return EMPTY_CLOSE_HANDLER; } return iter::close; } static void close(final Deque> closeHandlers) { Exception 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); //NOSONAR } } } return arg; } private long checkArgPositive(final long arg, final String argNameOrErrorMsg) { if (arg <= 0) { try { N.checkArgPositive(arg, argNameOrErrorMsg); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); //NOSONAR } } } 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); //NOSONAR } } } 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); //NOSONAR } } } return obj; } @SuppressWarnings("rawtypes") ARG checkArgNotNullOrEmpty(final ARG obj, final String errorMessage) { if (obj == null || obj.size() == 0) { try { N.checkArgNotNullOrEmpty(obj, errorMessage); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); //NOSONAR } } } 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); //NOSONAR } } } } /** * * @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); //NOSONAR } } } } /** * * @param b * @param errorMessageTemplate * @param p1 * @param p2 */ private void checkArgument(boolean b, String errorMessageTemplate, long p1, long p2) { if (!b) { try { N.checkArgument(b, errorMessageTemplate, p1, p2); } finally { try { close(); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); //NOSONAR } } } } ObjIteratorEx newObjIteratorEx(final ExceptionalIterator elements) { return new ObjIteratorEx<>() { @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); } } @Override public void advance(long n) { try { elements.advance(n); } catch (Exception e) { throw ExceptionUtil.toRuntimeException(e); } } @Override public long count() { try { return elements.count(); } 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() ? 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) s.iteratorEx(); } /** * The Class ExceptionalIterator. * * @param * @param */ @Internal @com.landawn.abacus.annotation.Immutable public abstract static 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(); } }; /** * * * @param * @param * @return */ public static ExceptionalIterator empty() { return EMPTY; } /** * * * @param * @param * @param val * @return */ public static ExceptionalIterator just(final T val) { return new ExceptionalIterator<>() { private boolean done = false; @Override public boolean hasNext() { return !done; } @Override public T next() { if (done) { throw new NoSuchElementException(); } done = true; return val; } }; } /** * * * @param * @param * @param a * @return */ @SafeVarargs public static ExceptionalIterator of(final T... a) { return N.isNullOrEmpty(a) ? EMPTY : of(a, 0, a.length); } /** * * * @param * @param * @param a * @param fromIndex * @param toIndex * @return */ public static ExceptionalIterator of(final T[] a, final int fromIndex, final int toIndex) { N.checkFromToIndex(fromIndex, toIndex, a == null ? 0 : a.length); if (fromIndex == toIndex) { return EMPTY; } return new ExceptionalIterator<>() { private int cursor = fromIndex; @Override public boolean hasNext() { return cursor < toIndex; } @Override public T next() { if (cursor >= toIndex) { throw new NoSuchElementException(); } return a[cursor++]; } @Override public void advance(long n) throws E { if (n > toIndex - cursor) { cursor = toIndex; } else { cursor += n; } } @Override public long count() { return toIndex - cursor; //NOSONAR } }; } /** * * * @param * @param * @param iter * @return */ public static ExceptionalIterator of(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 arraySupplier // * @return // */ // @Beta // 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) { // init(); // } // // return position < len; // } // // @Override // public T next() throws E { // if (!isInitialized) { // init(); // } // // if (position >= len) { // throw new NoSuchElementException(); // } // // return a[position++]; // } // // @Override // public long count() throws E { // if (!isInitialized) { // init(); // } // // return len - position; //NOSONAR // } // // @Override // public void advance(long n) throws E { // N.checkArgNotNegative(n, "n"); // // if (!isInitialized) { // init(); // } // // if (n > len - position) { // position = len; // } else { // position += n; // } // // } // // private void init() throws E { // if (!isInitialized) { // isInitialized = true; // a = arraySupplier.get(); // len = N.len(a); // } // } // }; // } /** * Lazy evaluation. * * @param * @param * @param iteratorSupplier * @return */ public static ExceptionalIterator defer(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) { init(); } return iter.hasNext(); } @Override public T next() throws E { if (!isInitialized) { init(); } return iter.next(); } @Override public void advance(long n) throws E { N.checkArgNotNegative(n, "n"); if (!isInitialized) { init(); } iter.advance(n); } @Override public long count() throws E { if (!isInitialized) { init(); } return iter.count(); } @Override public void close() throws E { if (!isInitialized) { init(); } iter.close(); } private void init() throws E { if (!isInitialized) { isInitialized = true; iter = iteratorSupplier.get(); } } }; } /** * * * @param * @param * @param a * @return */ public static ExceptionalIterator concat(final ExceptionalIterator... a) { return concat(N.asList(a)); } /** * * * @param * @param * @param c * @return */ public static ExceptionalIterator concat(final Collection> c) { if (N.isNullOrEmpty(c)) { return ExceptionalIterator.empty(); } return new ExceptionalIterator<>() { private final Iterator> iter = c.iterator(); private ExceptionalIterator cur; @Override public boolean hasNext() throws E { while ((cur == null || !cur.hasNext()) && iter.hasNext()) { cur = iter.next(); } return cur != null && cur.hasNext(); } @Override public T next() throws E { if ((cur == null || !cur.hasNext()) && !hasNext()) { throw new NoSuchElementException(); } return cur.next(); } }; } /** * 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 CheckedStream extends ExceptionalStream { CheckedStream(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} // * // * @deprecated Mostly it's for android. // */ // @Beta // @Deprecated // public static final 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 Stream stream) { // return ExceptionalStream. of(stream); // } // // public static ExceptionalStream of(final java.util.stream.Stream stream) { // return ExceptionalStream. of(stream); // } // // 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 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); // } // // // @Beta // // public static ExceptionalStream from(final Throwables.Supplier, RuntimeException> supplier) { // // return ExceptionalStream. from(supplier); // // } // // public static ExceptionalStream defer( // final Throwables.Supplier, RuntimeException> supplier) { // return ExceptionalStream. defer(supplier); // } // // 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 Iterable... a) { // return ExceptionalStream. concat(a); // } // // @SafeVarargs // public static ExceptionalStream concat(final Iterator... 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 Iterable a, final Iterable b, // final Throwables.BiFunction zipFunction) { // return ExceptionalStream. zip(a, b, zipFunction); // } // // public static ExceptionalStream zip(final Iterable a, final Iterable b, // final Iterable 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 Iterable a, final Iterable b, final A valueForNoneA, // final B valueForNoneB, final Throwables.BiFunction zipFunction) { // return ExceptionalStream. zip(a, b, valueForNoneA, valueForNoneB, zipFunction); // } // // public static ExceptionalStream zip(final Iterable a, final Iterable b, // final Iterable 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 Iterable a, final Iterable b, // final Throwables.BiFunction nextSelector) { // return ExceptionalStream. merge(a, b, nextSelector); // } // // public static ExceptionalStream merge(final Iterable a, final Iterable b, // final Iterable 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); // } // } }