com.landawn.abacus.util.ExceptionalStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-util-se Show documentation
Show all versions of abacus-util-se Show documentation
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
/*
* Copyright (C) 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.Reader;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.security.SecureRandom;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import com.landawn.abacus.DataSet;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.IntermediateOp;
import com.landawn.abacus.annotation.LazyEvaluation;
import com.landawn.abacus.annotation.SequentialOnly;
import com.landawn.abacus.annotation.TerminalOp;
import com.landawn.abacus.annotation.TerminalOpTriggered;
import com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.Fn.Factory;
import com.landawn.abacus.util.Fn.Fnn;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.If.OrElse;
import com.landawn.abacus.util.StringUtil.Strings;
import com.landawn.abacus.util.u.Holder;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalLong;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BinaryOperator;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.stream.Collector;
import com.landawn.abacus.util.stream.Collectors;
/**
* The Stream will be automatically closed after execution(A terminal method is executed/triggered).
*
* @author Haiyang Li
* @param
* @param
* @since 1.3
*/
@LazyEvaluation
@SequentialOnly
public class ExceptionalStream implements Closeable {
static final Logger logger = LoggerFactory.getLogger(ExceptionalStream.class);
static final Random RAND = new SecureRandom();
static final Throwables.Function, Object>, Object, Exception> KK = new Throwables.Function, Object>, Object, Exception>() {
@Override
public Object apply(Map.Entry, Object> t) throws Exception {
return t.getKey().val();
}
};
private final ExceptionalIterator elements;
private final boolean sorted;
private final Comparator super T> comparator;
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 super T> comparator,
final Deque> closeHandlers) {
this.elements = iter;
this.sorted = sorted;
this.comparator = 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, final Class exceptionType) {
return of(e);
}
/**
* Returns an empty {@code Stream} if the specified {@code t} is null.
*
* @param
* @param
* @param e
* @return
*/
public static ExceptionalStream ofNullable(final T e) {
if (e == null) {
return empty();
}
return of(e);
}
/**
*
* @param
* @param
* @param a
* @return
*/
public static ExceptionalStream of(final T... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
final int len = N.len(a);
return newStream(new ExceptionalIterator() {
private int position = 0;
@Override
public boolean hasNext() throws E {
return position < len;
}
@Override
public T next() throws E {
if (position >= len) {
throw new NoSuchElementException();
}
return a[position++];
}
@Override
public long count() throws E {
return len - position;
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (n > len - position) {
position = len;
} else {
position += n;
}
}
});
}
/**
*
* @param
* @param
* @param c
* @return
*/
public static ExceptionalStream of(final Collection extends T> c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
@SuppressWarnings("deprecation")
final T[] a = (T[]) InternalUtil.getInternalArray(c);
if (a != null) {
final int len = c.size();
return newStream(new ExceptionalIterator() {
private int position = 0;
@Override
public boolean hasNext() throws E {
return position < len;
}
@Override
public T next() throws E {
if (position >= len) {
throw new NoSuchElementException();
}
return a[position++];
}
@Override
public long count() throws E {
return len - position;
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (n > len - position) {
position = len;
} else {
position += n;
}
}
});
}
return of(c.iterator());
}
/**
*
* @param
* @param
* @param iter
* @return
*/
public static ExceptionalStream of(final Iterator extends T> iter) {
if (iter == null) {
return empty();
}
return newStream(ExceptionalIterator. wrap(iter));
}
/**
*
* @param
* @param
* @param iterable
* @return
*/
public static ExceptionalStream of(final Iterable extends T> iterable) {
if (iterable == null) {
return empty();
}
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 (m == null) {
return empty();
}
return of(m.entrySet());
}
/**
*
* @param
* @param
* @param c
* @param exceptionType
* @return
*/
public static ExceptionalStream of(final Collection extends T> c, final Class exceptionType) {
return of(c);
}
/**
*
* @param
* @param
* @param iter
* @param exceptionType
* @return
*/
public static ExceptionalStream of(final Iterator extends T> iter, final Class exceptionType) {
return of(iter);
}
/**
*
* @param
* @param
* @param iterable
* @param exceptionType
* @return
*/
public static ExceptionalStream of(final Iterable extends T> iterable, final Class exceptionType) {
return of(iterable);
}
/**
*
* @param the key type
* @param the value type
* @param
* @param m
* @param exceptionType
* @return
*/
public static ExceptionalStream, E> of(final Map m, final Class exceptionType) {
return of(m);
}
/**
*
* @param
* @param a
* @return
*/
public static ExceptionalStream of(final int[] a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
final int len = N.len(a);
return newStream(new ExceptionalIterator() {
private int position = 0;
@Override
public boolean hasNext() throws E {
return position < len;
}
@Override
public Integer next() throws E {
return a[position++];
}
@Override
public long count() throws E {
return len - position;
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (n > len - position) {
position = len;
} else {
position += n;
}
}
});
}
/**
*
* @param
* @param a
* @return
*/
public static ExceptionalStream of(final long[] a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
final int len = N.len(a);
return newStream(new ExceptionalIterator() {
private int position = 0;
@Override
public boolean hasNext() throws E {
return position < len;
}
@Override
public Long next() throws E {
return a[position++];
}
@Override
public long count() throws E {
return len - position;
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (n > len - position) {
position = len;
} else {
position += n;
}
}
});
}
/**
*
* @param
* @param a
* @return
*/
public static ExceptionalStream of(final double[] a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
final int len = N.len(a);
return newStream(new ExceptionalIterator() {
private int position = 0;
@Override
public boolean hasNext() throws E {
return position < len;
}
@Override
public Double next() throws E {
return a[position++];
}
@Override
public long count() throws E {
return len - position;
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (n > len - position) {
position = len;
} else {
position += n;
}
}
});
}
/**
* Lazy evaluation.
*
*
* This is equal to: {@code ExceptionalStream.just(supplier).flattMap(it -> it.get())}.
*
* @param supplier
* @return
*/
@Beta
public static ExceptionalStream of(final Throwables.Supplier, ? extends E> supplier) {
N.checkArgNotNull(supplier, "supplier");
return ExceptionalStream., ? extends E>, E> just(supplier)
.flattMap(new Throwables.Function, ? extends E>, Collection extends T>, E>() {
@Override
public Collection extends T> apply(Throwables.Supplier, ? extends E> t) throws E {
return t.get();
}
});
}
/**
* Lazy evaluation.
*
*
* This is equal to: {@code ExceptionalStream.just(supplier).flatMap(it -> it.get())}.
*
* @param supplier
* @return
*/
public static ExceptionalStream from(
final Throwables.Supplier, ? extends E> supplier) {
N.checkArgNotNull(supplier, "supplier");
return ExceptionalStream., ? extends E>, E> just(supplier)
.flatMap(
new Throwables.Function, ? extends E>, ExceptionalStream extends T, ? extends E>, E>() {
@Override
public ExceptionalStream extends T, ? extends E> apply(
Throwables.Supplier, ? extends E> t) throws E {
return t.get();
}
});
}
public static ExceptionalStream ofKeys(final Map map) {
if (N.isNullOrEmpty(map)) {
return empty();
}
return of(map.keySet());
}
public static ExceptionalStream ofValues(final Map, V> map) {
if (N.isNullOrEmpty(map)) {
return empty();
}
return of(map.values());
}
/**
*
* @param
* @param
* @param hasNext
* @param next
* @return
*/
public static ExceptionalStream iterate(final Throwables.BooleanSupplier extends E> hasNext,
final Throwables.Supplier extends T, E> next) {
N.checkArgNotNull(hasNext, "hasNext");
N.checkArgNotNull(next, "next");
return newStream(new ExceptionalIterator() {
private boolean hasNextVal = false;
@Override
public boolean hasNext() throws E {
if (hasNextVal == false) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public T next() throws E {
if (hasNextVal == false && hasNext() == false) {
throw new NoSuchElementException();
}
hasNextVal = false;
return next.get();
}
});
}
/**
*
* @param
* @param
* @param init
* @param hasNext
* @param f
* @return
*/
public static ExceptionalStream iterate(final T init, final Throwables.BooleanSupplier extends E> hasNext,
final Throwables.UnaryOperator f) {
N.checkArgNotNull(hasNext, "hasNext");
N.checkArgNotNull(f, "f");
return newStream(new ExceptionalIterator() {
private final T NONE = (T) N.NULL_MASK;
private T t = NONE;
private boolean hasNextVal = false;
@Override
public boolean hasNext() throws E {
if (hasNextVal == false) {
hasNextVal = hasNext.getAsBoolean();
}
return hasNextVal;
}
@Override
public T next() throws E {
if (hasNextVal == false && hasNext() == false) {
throw new NoSuchElementException();
}
hasNextVal = false;
return t = (t == NONE) ? init : f.apply(t);
}
});
}
/**
*
* @param
* @param
* @param init
* @param hasNext
* @param f
* @return
*/
public static ExceptionalStream iterate(final T init, final Throwables.Predicate super T, ? extends E> hasNext,
final Throwables.UnaryOperator f) {
N.checkArgNotNull(hasNext, "hasNext");
N.checkArgNotNull(f, "f");
return newStream(new ExceptionalIterator() {
private final T NONE = (T) N.NULL_MASK;
private T t = NONE;
private T cur = NONE;
private boolean hasMore = true;
private boolean hasNextVal = false;
@Override
public boolean hasNext() throws E {
if (hasNextVal == false && hasMore) {
hasNextVal = hasNext.test((cur = (t == NONE ? init : f.apply(t))));
if (hasNextVal == false) {
hasMore = false;
}
}
return hasNextVal;
}
@Override
public T next() throws E {
if (hasNextVal == false && hasNext() == false) {
throw new NoSuchElementException();
}
t = cur;
cur = NONE;
hasNextVal = false;
return t;
}
});
}
/**
*
* @param
* @param
* @param init
* @param f
* @return
*/
public static ExceptionalStream iterate(final T init, final Throwables.UnaryOperator f) {
N.checkArgNotNull(f, "f");
return newStream(new ExceptionalIterator() {
private final T NONE = (T) N.NULL_MASK;
private T t = NONE;
@Override
public boolean hasNext() throws E {
return true;
}
@Override
public T next() throws E {
return t = t == NONE ? init : f.apply(t);
}
});
}
public static ExceptionalStream generate(final Throwables.Supplier supplier) {
N.checkArgNotNull(supplier, "supplier");
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return true;
}
@Override
public T next() throws E {
return supplier.get();
}
});
}
public static ExceptionalStream repeat(final T element, final long n) {
N.checkArgNotNegative(n, "n");
if (n == 0) {
return empty();
}
return newStream(new ExceptionalIterator() {
private long cnt = n;
@Override
public boolean hasNext() throws E {
return cnt > 0;
}
@Override
public T next() throws E {
if (cnt-- <= 0) {
throw new NoSuchElementException();
}
return element;
}
});
}
/**
*
* @param file
* @return
*/
public static ExceptionalStream lines(final File file) {
return lines(file, Charsets.UTF_8);
}
/**
*
* @param file
* @param charset
* @return
*/
public static ExceptionalStream lines(final File file, final Charset charset) {
N.checkArgNotNull(file, "file");
final ExceptionalIterator iter = createLazyLineIterator(file, null, charset, null, true);
return newStream(iter).onClose(new Throwables.Runnable() {
@Override
public void run() throws IOException {
iter.close();
}
});
}
/**
*
* @param path
* @return
*/
public static ExceptionalStream lines(final Path path) {
return lines(path, Charsets.UTF_8);
}
/**
*
* @param path
* @param charset
* @return
*/
public static ExceptionalStream lines(final Path path, final Charset charset) {
N.checkArgNotNull(path, "path");
final ExceptionalIterator iter = createLazyLineIterator(null, path, charset, null, true);
return newStream(iter).onClose(new Throwables.Runnable() {
@Override
public void run() throws IOException {
iter.close();
}
});
}
/**
*
* @param reader
* @return
*/
public static ExceptionalStream lines(final Reader reader) {
N.checkArgNotNull(reader, "reader");
return newStream(createLazyLineIterator(null, null, Charsets.UTF_8, reader, false));
}
public static ExceptionalStream listFiles(final File parentPath) {
if (!parentPath.exists()) {
return empty();
}
return of(parentPath.listFiles());
}
public static ExceptionalStream listFiles(final File parentPath, final boolean recursively) {
if (!parentPath.exists()) {
return empty();
} else if (recursively == false) {
return of(parentPath.listFiles());
}
final ExceptionalIterator iter = new ExceptionalIterator() {
private final Queue paths = N.asLinkedList(parentPath);
private File[] subFiles = null;
private int cursor = 0;
@Override
public boolean hasNext() {
if ((subFiles == null || cursor >= subFiles.length) && paths.size() > 0) {
cursor = 0;
subFiles = null;
while (paths.size() > 0) {
subFiles = paths.poll().listFiles();
if (N.notNullOrEmpty(subFiles)) {
break;
}
}
}
return subFiles != null && cursor < subFiles.length;
}
@Override
public File next() {
if (hasNext() == false) {
throw new NoSuchElementException();
}
if (subFiles[cursor].isDirectory()) {
paths.offer(subFiles[cursor]);
}
return subFiles[cursor++];
}
};
return newStream(iter);
}
/**
* Creates the lazy line iterator.
*
* @param file
* @param path
* @param charset
* @param reader
* @param closeReader
* @return
*/
private static ExceptionalIterator createLazyLineIterator(final File file, final Path path, final Charset charset, final Reader reader,
final boolean closeReader) {
return ExceptionalIterator.of(new Throwables.Supplier, IOException>() {
private ExceptionalIterator lazyIter = null;
@Override
public synchronized ExceptionalIterator get() {
if (lazyIter == null) {
lazyIter = new ExceptionalIterator() {
private BufferedReader bufferedReader;
{
if (reader != null) {
bufferedReader = reader instanceof BufferedReader ? ((BufferedReader) reader) : new BufferedReader(reader);
} else if (file != null) {
bufferedReader = IOUtil.newBufferedReader(file, charset == null ? Charsets.UTF_8 : charset);
} else {
bufferedReader = IOUtil.newBufferedReader(path, charset == null ? Charsets.UTF_8 : charset);
}
}
private String cachedLine;
private boolean finished = false;
@Override
public boolean hasNext() throws IOException {
if (this.cachedLine != null) {
return true;
} else if (this.finished) {
return false;
} else {
this.cachedLine = this.bufferedReader.readLine();
if (this.cachedLine == null) {
this.finished = true;
return false;
} else {
return true;
}
}
}
@Override
public String next() throws IOException {
if (!this.hasNext()) {
throw new NoSuchElementException("No more lines");
} else {
String res = this.cachedLine;
this.cachedLine = null;
return res;
}
}
@Override
public void close() throws IOException {
if (closeReader) {
IOUtil.close(bufferedReader);
}
}
};
}
return lazyIter;
}
});
}
@SafeVarargs
public static ExceptionalStream concat(final T[]... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return of(Iterators.concat(a));
}
@SafeVarargs
public static ExceptionalStream concat(final Collection extends T>... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return of(Iterators.concat(a));
}
/**
*
* @param
* @param
* @param a
* @return
*/
@SafeVarargs
public static ExceptionalStream concat(final ExceptionalStream extends T, E>... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return concat(Array.asList(a));
}
/**
*
* @param
* @param
* @param c
* @return
*/
public static ExceptionalStream concat(final Collection extends ExceptionalStream extends T, E>> c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
return newStream(new ExceptionalIterator() {
private final Iterator extends ExceptionalStream extends T, E>> iterators = c.iterator();
private ExceptionalStream extends T, E> cur;
private ExceptionalIterator extends T, E> iter;
@Override
public boolean hasNext() throws E {
while ((iter == null || iter.hasNext() == false) && iterators.hasNext()) {
if (cur != null) {
cur.close();
}
cur = iterators.next();
iter = cur.elements;
}
return iter != null && iter.hasNext();
}
@Override
public T next() throws E {
if ((iter == null || iter.hasNext() == false) && hasNext() == false) {
throw new NoSuchElementException();
}
return iter.next();
}
}, mergeCloseHandlers(c));
}
/**
* Zip together the "a" and "b" arrays until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final A[] a, final B[] b,
final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return zip(ObjIterator.of(a), ObjIterator.of(b), zipFunction);
}
/**
* Zip together the "a", "b" and "c" arrays until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final A[] a, final B[] b, final C[] c,
final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return zip(ObjIterator.of(a), ObjIterator.of(b), ObjIterator.of(c), zipFunction);
}
/**
* Zip together the "a" and "b" arrays until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final Collection extends A> a, final Collection extends B> b,
final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return zip(N.iterate(a), N.iterate(b), zipFunction);
}
/**
* Zip together the "a", "b" and "c" arrays until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final Collection extends A> a, final Collection extends B> b,
final Collection extends C> c, final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return zip(N.iterate(a), N.iterate(b), N.iterate(c), zipFunction);
}
/**
* Zip together the "a" and "b" iterators until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final Iterator extends A> a, final Iterator extends B> b,
final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return a.hasNext() && b.hasNext();
}
@Override
public T next() throws E {
return zipFunction.apply(a.next(), b.next());
}
});
}
/**
* Zip together the "a", "b" and "c" iterators until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final Iterator extends A> a, final Iterator extends B> b,
final Iterator extends C> c, final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return a.hasNext() && b.hasNext() && c.hasNext();
}
@Override
public T next() throws E {
return zipFunction.apply(a.next(), b.next(), c.next());
}
});
}
/**
* Zip together the "a" and "b" streams until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final ExceptionalStream extends A, E> a,
final ExceptionalStream extends B, E> b, final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
private final ExceptionalIterator extends A, E> iterA = a.elements;
private final ExceptionalIterator extends B, E> iterB = b.elements;
@Override
public boolean hasNext() throws E {
return iterA.hasNext() && iterB.hasNext();
}
@Override
public T next() throws E {
return zipFunction.apply(iterA.next(), iterB.next());
}
}, mergeCloseHandlers(Array.asList(a, b)));
}
/**
* Zip together the "a", "b" and "c" streams until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @return
*/
public static ExceptionalStream zip(final ExceptionalStream extends A, E> a,
final ExceptionalStream extends B, E> b, final ExceptionalStream extends C, E> c,
final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
private final ExceptionalIterator extends A, E> iterA = a.elements;
private final ExceptionalIterator extends B, E> iterB = b.elements;
private final ExceptionalIterator extends C, E> iterC = c.elements;
@Override
public boolean hasNext() throws E {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public T next() throws E {
return zipFunction.apply(iterA.next(), iterB.next(), iterC.next());
}
}, mergeCloseHandlers(Array.asList(a, b, c)));
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final A[] a, final B[] b, final A valueForNoneA, final B valueForNoneB,
final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return zip(ObjIterator.of(a), ObjIterator.of(b), valueForNoneA, valueForNoneB, zipFunction);
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA,
final B valueForNoneB, final C valueForNoneC, final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return zip(ObjIterator.of(a), ObjIterator.of(b), ObjIterator.of(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction);
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final Collection extends A> a, final Collection extends B> b,
final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return zip(N.iterate(a), N.iterate(b), valueForNoneA, valueForNoneB, zipFunction);
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final Collection extends A> a, final Collection extends B> b,
final Collection extends C> c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC,
final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return zip(N.iterate(a), N.iterate(b), N.iterate(c), valueForNoneA, valueForNoneB, valueForNoneC, zipFunction);
}
/**
* Zip together the "a" and "b" iterators until all of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param valueForNoneA value to fill if "a" runs out of values first.
* @param valueForNoneB value to fill if "b" runs out of values first.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final Iterator extends A> a, final Iterator extends B> b,
final A valueForNoneA, final B valueForNoneB, final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return a.hasNext() || b.hasNext();
}
@Override
public T next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
return zipFunction.apply(a.hasNext() ? a.next() : valueForNoneA, b.hasNext() ? b.next() : valueForNoneB);
}
});
}
/**
* Zip together the "a", "b" and "c" iterators until all of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @param valueForNoneA value to fill if "a" runs out of values.
* @param valueForNoneB value to fill if "b" runs out of values.
* @param valueForNoneC value to fill if "c" runs out of values.
* @param zipFunction
* @return
*/
public static ExceptionalStream zip(final Iterator extends A> a, final Iterator extends B> b,
final Iterator extends C> c, final A valueForNoneA, final B valueForNoneB, final C valueForNoneC,
final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return a.hasNext() || b.hasNext() || c.hasNext();
}
@Override
public T next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
return zipFunction.apply(a.hasNext() ? a.next() : valueForNoneA, b.hasNext() ? b.next() : valueForNoneB,
c.hasNext() ? c.next() : valueForNoneC);
}
});
}
/**
* Zip together the "a" and "b" streams until one of them runs out of values.
* Each pair of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @return
*/
public static ExceptionalStream zip(final ExceptionalStream extends A, E> a,
final ExceptionalStream extends B, E> b, final A valueForNoneA, final B valueForNoneB,
final Throwables.BiFunction super A, ? super B, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
private final ExceptionalIterator extends A, E> iterA = a.elements;
private final ExceptionalIterator extends B, E> iterB = b.elements;
@Override
public boolean hasNext() throws E {
return iterA.hasNext() || iterB.hasNext();
}
@Override
public T next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB);
}
}, mergeCloseHandlers(Array.asList(a, b)));
}
/**
* Zip together the "a", "b" and "c" streams until one of them runs out of values.
* Each triple of values is combined into a single value using the supplied zipFunction function.
*
* @param a
* @param b
* @param c
* @return
*/
public static ExceptionalStream zip(final ExceptionalStream extends A, E> a,
final ExceptionalStream extends B, E> b, final ExceptionalStream extends C, E> c, final A valueForNoneA, final B valueForNoneB,
final C valueForNoneC, final Throwables.TriFunction super A, ? super B, ? super C, T, ? extends E> zipFunction) {
return newStream(new ExceptionalIterator() {
private final ExceptionalIterator extends A, E> iterA = a.elements;
private final ExceptionalIterator extends B, E> iterB = b.elements;
private final ExceptionalIterator extends C, E> iterC = c.elements;
@Override
public boolean hasNext() throws E {
return iterA.hasNext() || iterB.hasNext() || iterC.hasNext();
}
@Override
public T next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
return zipFunction.apply(iterA.hasNext() ? iterA.next() : valueForNoneA, iterB.hasNext() ? iterB.next() : valueForNoneB,
iterC.hasNext() ? iterC.next() : valueForNoneC);
}
}, mergeCloseHandlers(Array.asList(a, b, c)));
}
private static Deque> mergeCloseHandlers(
Collection extends ExceptionalStream, E>> closeHandlersList) {
if (N.isNullOrEmpty(closeHandlersList)) {
return null;
}
int count = 0;
for (ExceptionalStream, E> s : closeHandlersList) {
count += N.size(s.closeHandlers);
}
if (count == 0) {
return null;
}
final Deque> newCloseHandlers = new ArrayDeque<>(count);
for (ExceptionalStream, E> s : closeHandlersList) {
if (N.notNullOrEmpty(s.closeHandlers)) {
newCloseHandlers.addAll(s.closeHandlers);
}
}
return newCloseHandlers;
}
/**
*
* @param predicate
* @return
*/
@IntermediateOp
public ExceptionalStream filter(final Throwables.Predicate super T, ? extends E> predicate) {
assertNotClosed();
return newStream(new ExceptionalIterator() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() throws E {
if (hasNext == false) {
while (elements.hasNext()) {
next = elements.next();
if (predicate.test(next)) {
hasNext = true;
break;
}
}
}
return hasNext;
}
@Override
public T next() throws E {
if (hasNext == false && hasNext() == false) {
throw new NoSuchElementException();
}
hasNext = false;
return next;
}
}, sorted, comparator, closeHandlers);
}
/**
*
* @param predicate
* @param actionOnDroppedItem
* @return
*/
@IntermediateOp
public ExceptionalStream filter(final Throwables.Predicate super T, ? extends E> predicate,
final Throwables.Consumer super T, ? extends E> actionOnDroppedItem) {
assertNotClosed();
return filter(new Throwables.Predicate() {
@Override
public boolean test(T value) throws E {
if (!predicate.test(value)) {
actionOnDroppedItem.accept(value);
return false;
}
return true;
}
});
}
/**
*
* @param predicate
* @return
*/
@IntermediateOp
public ExceptionalStream takeWhile(final Throwables.Predicate super T, ? extends E> predicate) {
assertNotClosed();
return newStream(new ExceptionalIterator() {
private boolean hasMore = true;
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() throws E {
if (hasNext == false && hasMore && elements.hasNext()) {
next = elements.next();
if (predicate.test(next)) {
hasNext = true;
} else {
hasMore = false;
}
}
return hasNext;
}
@Override
public T next() throws E {
if (hasNext == false && hasNext() == false) {
throw new NoSuchElementException();
}
hasNext = false;
return next;
}
}, sorted, comparator, closeHandlers);
}
/**
*
* @param predicate
* @return
*/
@IntermediateOp
public ExceptionalStream dropWhile(final Throwables.Predicate super T, ? extends E> predicate) {
assertNotClosed();
return newStream(new ExceptionalIterator() {
private boolean hasNext = false;
private T next = null;
private boolean dropped = false;
@Override
public boolean hasNext() throws E {
if (hasNext == false) {
if (dropped == false) {
dropped = true;
while (elements.hasNext()) {
next = elements.next();
if (predicate.test(next) == false) {
hasNext = true;
break;
}
}
} else if (elements.hasNext()) {
next = elements.next();
hasNext = true;
}
}
return hasNext;
}
@Override
public T next() throws E {
if (hasNext == false && hasNext() == false) {
throw new NoSuchElementException();
}
hasNext = false;
return next;
}
}, sorted, comparator, closeHandlers);
}
/**
*
* @param predicate
* @param actionOnDroppedItem
* @return
*/
@IntermediateOp
public ExceptionalStream dropWhile(final Throwables.Predicate super T, ? extends E> predicate,
final Throwables.Consumer super T, ? extends E> actionOnDroppedItem) {
assertNotClosed();
return filter(new Throwables.Predicate() {
@Override
public boolean test(T value) throws E {
if (!predicate.test(value)) {
actionOnDroppedItem.accept(value);
return false;
}
return true;
}
});
}
/**
*
* @param predicate
* @return
*/
@IntermediateOp
@Beta
public ExceptionalStream skipUntil(final Throwables.Predicate super T, ? extends E> predicate) {
return dropWhile(Fnn.not(predicate));
}
/**
* Distinct and filter by occurrences.
*
* @return
*/
@IntermediateOp
public ExceptionalStream distinct() {
assertNotClosed();
final Set