Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.landawn.abacus.util.ExceptionalStream Maven / Gradle / Ivy
/*
* 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.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Executor;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.annotation.SequentialOnly;
import com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.exception.UncheckedSQLException;
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.Suppliers;
import com.landawn.abacus.util.StringUtil.Strings;
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.function.BiConsumer;
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;
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).
*
* @since 1.3
*
* @author Haiyang Li
*/
@SequentialOnly
public class ExceptionalStream implements AutoCloseable {
static final Logger logger = LoggerFactory.getLogger(ExceptionalStream.class);
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;
}
public static ExceptionalStream empty() {
return new ExceptionalStream<>(ExceptionalIterator.EMPTY);
}
public static ExceptionalStream just(final T e) {
return of(e);
}
public static ExceptionalStream ofNullable(final T e) {
if (e == null) {
return empty();
}
return of(e);
}
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;
}
position += n;
}
});
}
public static ExceptionalStream of(final Collection extends T> c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
return of(c.iterator());
}
public static ExceptionalStream of(final Iterator extends T> iter) {
if (iter == null) {
return empty();
}
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return iter.hasNext();
}
@Override
public T next() throws E {
return iter.next();
}
});
}
public static ExceptionalStream of(final Iterable extends T> iterable) {
if (iterable == null) {
return empty();
}
return of(iterable.iterator());
}
public static ExceptionalStream, E> of(final Map m) {
if (m == null) {
return empty();
}
return of(m.entrySet());
}
public static ExceptionalStream of(final Stream extends T> stream) {
if (stream == null) {
return empty();
}
final ExceptionalIterator iter = new ExceptionalIterator() {
private Stream extends T> s = stream;
private Iterator extends T> iter = null;
private boolean isInitialized = false;
@Override
public boolean hasNext() throws E {
if (isInitialized == false) {
init();
}
return iter.hasNext();
}
@Override
public T next() throws E {
if (isInitialized == false) {
init();
}
return iter.next();
}
@Override
public void skip(long n) throws E {
N.checkArgNotNegative(n, "n");
if (iter == null) {
s = s.skip(n);
} else {
super.skip(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 == false) {
isInitialized = true;
iter = stream.iterator();
}
}
};
return newStream(iter).onClose(new Try.Runnable() {
@Override
public void run() throws E {
iter.close();
}
});
}
public static ExceptionalStream of(final Collection extends T> c, final Class exceptionType) {
return of(c);
}
public static ExceptionalStream of(final Iterator extends T> iter, final Class exceptionType) {
return of(iter);
}
public static ExceptionalStream of(final Iterable extends T> iterable, final Class exceptionType) {
return of(iterable);
}
public static ExceptionalStream, E> of(final Map m, final Class exceptionType) {
return of(m);
}
public static ExceptionalStream of(final Stream extends T> stream, final Class exceptionType) {
return of(stream);
}
public static ExceptionalStream iterate(final Try.BooleanSupplier extends E> hasNext,
final Try.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();
}
});
}
public static ExceptionalStream iterate(final T init, final Try.BooleanSupplier extends E> hasNext,
final Try.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);
}
});
}
public static ExceptionalStream iterate(final T init, final Try.Predicate super T, ? extends E> hasNext,
final Try.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;
}
});
}
public static ExceptionalStream iterate(final T init, final Try.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 lines(final File file) {
return lines(file, Charsets.UTF_8);
}
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 Try.Runnable() {
@Override
public void run() throws IOException {
iter.close();
}
});
}
public static ExceptionalStream lines(final Path path) {
return lines(path, Charsets.UTF_8);
}
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 Try.Runnable() {
@Override
public void run() throws IOException {
iter.close();
}
});
}
public static ExceptionalStream lines(final Reader reader) {
N.checkArgNotNull(reader, "reader");
return newStream(createLazyLineIterator(null, null, Charsets.UTF_8, reader, false));
}
private static ExceptionalIterator createLazyLineIterator(final File file, final Path path, final Charset charset, final Reader reader,
final boolean closeReader) {
return ExceptionalIterator.of(new Try.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(reader);
}
}
};
}
return lazyIter;
}
});
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param resultSet
* @return
*/
public static ExceptionalStream rows(final ResultSet resultSet) {
return rows(Object[].class, resultSet);
}
/**
*
* @param resultSet
* @param closeResultSet
* @return
* @deprecated
*/
@Deprecated
static ExceptionalStream rows(final ResultSet resultSet, final boolean closeResultSet) {
return rows(Object[].class, resultSet, closeResultSet);
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param targetClass Array/List/Map or Entity with getter/setter methods.
* @param resultSet
* @return
*/
public static ExceptionalStream rows(final Class targetClass, final ResultSet resultSet) {
N.checkArgNotNull(targetClass, "targetClass");
N.checkArgNotNull(resultSet, "resultSet");
return rows(resultSet, JdbcUtil.BiRowMapper.to(targetClass));
}
/**
*
* @param targetClass Array/List/Map or Entity with getter/setter methods.
* @param resultSet
* @param closeResultSet
* @return
* @deprecated
*/
@Deprecated
static ExceptionalStream rows(final Class targetClass, final ResultSet resultSet, final boolean closeResultSet) {
N.checkArgNotNull(targetClass, "targetClass");
N.checkArgNotNull(resultSet, "resultSet");
if (closeResultSet) {
return rows(targetClass, resultSet).onClose(new Try.Runnable() {
@Override
public void run() throws SQLException {
JdbcUtil.closeQuietly(resultSet);
}
});
} else {
return rows(targetClass, resultSet);
}
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param resultSet
* @param rowMapper
* @return
*/
public static ExceptionalStream rows(final ResultSet resultSet, final JdbcUtil.RowMapper rowMapper) {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNull(rowMapper, "rowMapper");
final ExceptionalIterator iter = new ExceptionalIterator() {
private boolean hasNext;
@Override
public boolean hasNext() throws SQLException {
if (hasNext == false) {
hasNext = resultSet.next();
}
return hasNext;
}
@Override
public T next() throws SQLException {
if (hasNext() == false) {
throw new NoSuchElementException();
}
hasNext = false;
return rowMapper.apply(resultSet);
}
@Override
public void skip(long n) throws SQLException {
N.checkArgNotNegative(n, "n");
final long m = hasNext ? n - 1 : n;
JdbcUtil.skip(resultSet, m);
hasNext = false;
}
};
return newStream(iter);
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param resultSet
* @param rowMapper
* @return
*/
public static ExceptionalStream rows(final ResultSet resultSet, final JdbcUtil.BiRowMapper rowMapper) {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNull(rowMapper, "rowMapper");
final ExceptionalIterator iter = new ExceptionalIterator() {
private List columnLabels = null;
private boolean hasNext;
@Override
public boolean hasNext() throws SQLException {
if (hasNext == false) {
hasNext = resultSet.next();
}
return hasNext;
}
@Override
public T next() throws SQLException {
if (hasNext() == false) {
throw new NoSuchElementException();
}
hasNext = false;
if (columnLabels == null) {
columnLabels = JdbcUtil.getColumnLabelList(resultSet);
}
return rowMapper.apply(resultSet, columnLabels);
}
@Override
public void skip(long n) throws SQLException {
N.checkArgNotNegative(n, "n");
final long m = hasNext ? n - 1 : n;
JdbcUtil.skip(resultSet, m);
hasNext = false;
}
@Override
public long count() throws SQLException {
long cnt = 0;
while (resultSet.next()) {
cnt++;
}
return cnt;
}
};
return newStream(iter);
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param resultSet
* @param columnIndex starts from 0, not 1.
* @return
*/
public static ExceptionalStream rows(final ResultSet resultSet, final int columnIndex) {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNegative(columnIndex, "columnIndex");
final ExceptionalIterator iter = new ExceptionalIterator() {
private final int newColumnIndex = columnIndex + 1;
private boolean hasNext = false;
@Override
public boolean hasNext() throws SQLException {
if (hasNext == false) {
hasNext = resultSet.next();
}
return hasNext;
}
@Override
public T next() throws SQLException {
if (!hasNext()) {
throw new NoSuchElementException("No more rows");
}
final T next = (T) JdbcUtil.getColumnValue(resultSet, newColumnIndex);
hasNext = false;
return next;
}
@Override
public void skip(long n) throws SQLException {
N.checkArgNotNegative(n, "n");
final long m = hasNext ? n - 1 : n;
JdbcUtil.skip(resultSet, m);
hasNext = false;
}
};
return newStream(iter);
}
/**
*
* @param resultSet
* @param columnIndex starts from 0, not 1.
* @param closeResultSet
* @return
* @deprecated
*/
@Deprecated
static ExceptionalStream rows(final ResultSet resultSet, final int columnIndex, final boolean closeResultSet) {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNegative(columnIndex, "columnIndex");
if (closeResultSet) {
return (ExceptionalStream) rows(resultSet, columnIndex).onClose(new Try.Runnable() {
@Override
public void run() throws SQLException {
JdbcUtil.closeQuietly(resultSet);
}
});
} else {
return rows(resultSet, columnIndex);
}
}
/**
* It's user's responsibility to close the input resultSet
after the stream is finished.
*
* @param resultSet
* @param columnName
* @return
* @throws UncheckedSQLException
*/
public static ExceptionalStream rows(final ResultSet resultSet, final String columnName) throws UncheckedSQLException {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNullOrEmpty(columnName, "columnName");
final ExceptionalIterator iter = new ExceptionalIterator() {
private int columnIndex = -1;
private boolean hasNext = false;
@Override
public boolean hasNext() throws SQLException {
if (hasNext == false) {
hasNext = resultSet.next();
}
return hasNext;
}
@Override
public T next() throws SQLException {
if (!hasNext()) {
throw new NoSuchElementException("No more rows");
}
columnIndex = columnIndex == -1 ? getColumnIndex(resultSet, columnName) : columnIndex;
final T next = (T) JdbcUtil.getColumnValue(resultSet, columnIndex);
hasNext = false;
return next;
}
@Override
public void skip(long n) throws SQLException {
N.checkArgNotNegative(n, "n");
final long m = hasNext ? n - 1 : n;
JdbcUtil.skip(resultSet, m);
hasNext = false;
}
};
return newStream(iter);
}
/**
*
* @param resultSet
* @param columnName
* @param closeResultSet
* @return
* @deprecated
* @throws UncheckedSQLException
*/
@Deprecated
static ExceptionalStream rows(final ResultSet resultSet, final String columnName, final boolean closeResultSet)
throws UncheckedSQLException {
N.checkArgNotNull(resultSet, "resultSet");
N.checkArgNotNullOrEmpty(columnName, "columnName");
if (closeResultSet) {
return (ExceptionalStream) rows(resultSet, columnName).onClose(new Try.Runnable() {
@Override
public void run() throws SQLException {
JdbcUtil.closeQuietly(resultSet);
}
});
} else {
return rows(resultSet, columnName);
}
}
private static int getColumnIndex(final ResultSet resultSet, final String columnName) throws UncheckedSQLException {
int columnIndex = -1;
try {
final ResultSetMetaData rsmd = resultSet.getMetaData();
final int columnCount = rsmd.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
if (JdbcUtil.getColumnLabel(rsmd, i).equals(columnName)) {
columnIndex = i - 1;
break;
}
}
} catch (SQLException e) {
throw new UncheckedSQLException(e);
}
N.checkArgument(columnIndex >= 0, "No column found by name %s", columnName);
return columnIndex;
}
@SafeVarargs
public static ExceptionalStream concat(final ExceptionalStream extends T, E>... a) {
if (N.isNullOrEmpty(a)) {
return empty();
}
return concat(N.asList(a));
}
public static ExceptionalStream concat(final Collection extends ExceptionalStream extends T, E>> c) {
if (N.isNullOrEmpty(c)) {
return empty();
}
final Deque> closeHandlers = new ArrayDeque<>();
for (ExceptionalStream extends T, E> e : c) {
if (N.notNullOrEmpty(e.closeHandlers)) {
closeHandlers.addAll(e.closeHandlers);
}
}
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();
}
}, closeHandlers);
}
public ExceptionalStream filter(final Try.Predicate super T, ? extends E> predicate) {
checkArgNotNull(predicate, "predicate");
return newStream(new ExceptionalIterator() {
private final T NONE = (T) N.NULL_MASK;
private T next = NONE;
@Override
public boolean hasNext() throws E {
while (next == NONE && elements.hasNext()) {
next = elements.next();
if (predicate.test(next)) {
break;
}
}
return next != NONE;
}
@Override
public T next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
final T result = next;
next = NONE;
return result;
}
}, sorted, comparator, closeHandlers);
}
public ExceptionalStream takeWhile(final Try.Predicate super T, ? extends E> predicate) {
checkArgNotNull(predicate, "predicate");
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);
}
public ExceptionalStream dropWhile(final Try.Predicate super T, ? extends E> predicate) {
checkArgNotNull(predicate, "predicate");
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);
}
/**
* Distinct and filter by occurrences.
*
* @param occurrencesFilter
* @return
*/
public ExceptionalStream distinct() {
final Set set = new HashSet<>();
return filter(new Try.Predicate() {
@Override
public boolean test(T value) {
return set.add(hashKey(value));
}
});
}
/**
* Distinct by the value mapped from keyMapper
*
* @param keyMapper don't change value of the input parameter.
* @return
*/
public ExceptionalStream distinctBy(final Try.Function super T, ?, ? extends E> keyMapper) {
checkArgNotNull(keyMapper, "keyMapper");
final Set set = new HashSet<>();
return filter(new Try.Predicate() {
@Override
public boolean test(T value) throws E {
return set.add(hashKey(keyMapper.apply(value)));
}
});
}
public ExceptionalStream map(final Try.Function super T, ? extends U, ? extends E> mapper) {
checkArgNotNull(mapper, "mapper");
return newStream(new ExceptionalIterator() {
@Override
public boolean hasNext() throws E {
return elements.hasNext();
}
@Override
public U next() throws E {
return mapper.apply(elements.next());
}
}, closeHandlers);
}
public ExceptionalStream flatMap(final Try.Function super T, ? extends ExceptionalStream extends R, ? extends E>, ? extends E> mapper) {
checkArgNotNull(mapper, "mapper");
final ExceptionalIterator iter = new ExceptionalIterator() {
private ExceptionalIterator extends R, ? extends E> cur = null;
private ExceptionalStream extends R, ? extends E> s = null;
private Try.Runnable closeHandle = null;
@Override
public boolean hasNext() throws E {
while ((cur == null || cur.hasNext() == false) && elements.hasNext()) {
if (closeHandle != null) {
final Try.Runnable tmp = closeHandle;
closeHandle = null;
tmp.run();
}
s = mapper.apply(elements.next());
if (N.notNullOrEmpty(s.closeHandlers)) {
closeHandle = new Try.Runnable() {
@Override
public void run() throws E {
s.close();
}
};
}
cur = s.elements;
}
return cur != null && cur.hasNext();
}
@Override
public R next() throws E {
if ((cur == null || cur.hasNext() == false) && hasNext() == false) {
throw new NoSuchElementException();
}
return cur.next();
}
@Override
public void close() throws E {
if (closeHandle != null) {
final Try.Runnable tmp = closeHandle;
closeHandle = null;
tmp.run();
}
}
};
final Deque> newCloseHandlers = new ArrayDeque<>(N.size(closeHandlers) + 1);
newCloseHandlers.add(new Try.Runnable() {
@Override
public void run() throws E {
iter.close();
}
});
if (N.notNullOrEmpty(closeHandlers)) {
newCloseHandlers.addAll(closeHandlers);
}
return newStream(iter, newCloseHandlers);
}
public ExceptionalStream flattMap(final Try.Function super T, ? extends Collection extends R>, ? extends E> mapper) {
checkArgNotNull(mapper, "mapper");
return flatMap(new Try.Function, E>() {
@Override
public ExceptionalStream extends R, ? extends E> apply(T t) throws E {
return ExceptionalStream.of(mapper.apply(t));
}
});
}
public ExceptionalStream slidingMap(Try.BiFunction super T, ? super T, R, E> mapper) {
return slidingMap(mapper, 1);
}
public ExceptionalStream slidingMap(Try.BiFunction super T, ? super T, R, E> mapper, int increment) {
return slidingMap(mapper, increment, false);
}
public ExceptionalStream slidingMap(final Try.BiFunction super T, ? super T, R, E> mapper, final int increment, final boolean ignoreNotPaired) {
final int windowSize = 2;
checkArgPositive(increment, "increment");
return newStream(new ExceptionalIterator() {
@SuppressWarnings("unchecked")
private final T NONE = (T) N.NULL_MASK;
private T prev = NONE;
private T _1 = NONE;
@Override
public boolean hasNext() throws E {
if (increment > windowSize && prev != NONE) {
int skipNum = increment - windowSize;
while (skipNum-- > 0 && elements.hasNext()) {
elements.next();
}
prev = NONE;
}
if (ignoreNotPaired && _1 == NONE && elements.hasNext()) {
_1 = elements.next();
}
return elements.hasNext();
}
@Override
public R next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
if (ignoreNotPaired) {
final R res = mapper.apply(_1, (prev = elements.next()));
_1 = increment == 1 ? prev : NONE;
return res;
} else {
if (increment == 1) {
return mapper.apply(prev == NONE ? elements.next() : prev, (prev = (elements.hasNext() ? elements.next() : null)));
} else {
return mapper.apply(elements.next(), (prev = (elements.hasNext() ? elements.next() : null)));
}
}
}
}, closeHandlers);
}
public ExceptionalStream slidingMap(Try.TriFunction super T, ? super T, ? super T, R, E> mapper) {
return slidingMap(mapper, 1);
}
public ExceptionalStream slidingMap(Try.TriFunction super T, ? super T, ? super T, R, E> mapper, int increment) {
return slidingMap(mapper, increment, false);
}
public ExceptionalStream slidingMap(final Try.TriFunction super T, ? super T, ? super T, R, E> mapper, final int increment,
final boolean ignoreNotPaired) {
final int windowSize = 3;
checkArgPositive(increment, "increment");
return newStream(new ExceptionalIterator() {
@SuppressWarnings("unchecked")
private final T NONE = (T) N.NULL_MASK;
private T prev = NONE;
private T prev2 = NONE;
private T _1 = NONE;
private T _2 = NONE;
@Override
public boolean hasNext() throws E {
if (increment > windowSize && prev != NONE) {
int skipNum = increment - windowSize;
while (skipNum-- > 0 && elements.hasNext()) {
elements.next();
}
prev = NONE;
}
if (ignoreNotPaired) {
if (_1 == NONE && elements.hasNext()) {
_1 = elements.next();
}
if (_2 == NONE && elements.hasNext()) {
_2 = elements.next();
}
}
return elements.hasNext();
}
@Override
public R next() throws E {
if (hasNext() == false) {
throw new NoSuchElementException();
}
if (ignoreNotPaired) {
final R res = mapper.apply(_1, _2, (prev = elements.next()));
_1 = increment == 1 ? _2 : (increment == 2 ? prev : NONE);
_2 = increment == 1 ? prev : NONE;
return res;
} else {
if (increment == 1) {
return mapper.apply(prev2 == NONE ? elements.next() : prev2,
(prev2 = (prev == NONE ? (elements.hasNext() ? elements.next() : null) : prev)),
(prev = (elements.hasNext() ? elements.next() : null)));
} else if (increment == 2) {
return mapper.apply(prev == NONE ? elements.next() : prev, elements.hasNext() ? elements.next() : null,
(prev = (elements.hasNext() ? elements.next() : null)));
} else {
return mapper.apply(elements.next(), elements.hasNext() ? elements.next() : null,
(prev = (elements.hasNext() ? elements.next() : null)));
}
}
}
}, closeHandlers);
}
/**
*
* @param keyMapper
* @return
*/
public ExceptionalStream>, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper) {
return groupBy(keyMapper, Suppliers.> ofMap());
}
/**
*
* @param keyMapper
* @param mapFactory
* @return
*/
public ExceptionalStream>, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Supplier extends Map>> mapFactory) {
return groupBy(keyMapper, Fn.FN. identity(), mapFactory);
}
/**
*
* @param keyMapper
* @param valueMapper
* @return
* @see Collectors#toMultimap(Function, Function)
*/
public ExceptionalStream>, E> groupBy(Try.Function super T, ? extends K, ? extends E> keyMapper,
Try.Function super T, ? extends V, E> valueMapper) {
return groupBy(keyMapper, valueMapper, Suppliers.> ofMap());
}
/**
*
* @param keyMapper
* @param valueMapper
* @param mapFactory
* @return
* @see Collectors#toMultimap(Function, Function, Supplier)
*/
public ExceptionalStream>, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Try.Function super T, ? extends V, ? extends E> valueMapper, final Supplier extends Map>> mapFactory) {
checkArgNotNull(keyMapper, "keyMapper");
checkArgNotNull(valueMapper, "valueMapper");
checkArgNotNull(mapFactory, "mapFactory");
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);
}
public ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Try.Function super T, ? extends V, ? extends E> valueMapper, Try.BinaryOperator mergeFunction) {
return groupBy(keyMapper, valueMapper, mergeFunction, Suppliers. ofMap());
}
/**
*
* @param keyMapper
* @param valueMapper
* @param mergeFunction
* @param mapFactory
* @return
* @see {@link Fn.FN#throwingMerger()}
* @see {@link Fn.FN#replacingMerger()}
* @see {@link Fn.FN#ignoringMerger()}
*/
public ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Try.Function super T, ? extends V, ? extends E> valueMapper, final Try.BinaryOperator mergeFunction,
final Supplier extends Map> mapFactory) {
checkArgNotNull(keyMapper, "keyMapper");
checkArgNotNull(valueMapper, "valueMapper");
checkArgNotNull(mergeFunction, "mergeFunction");
checkArgNotNull(mapFactory, "mapFactory");
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);
}
public ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Collector super T, A, D> downstream) throws E {
return groupBy(keyMapper, downstream, Suppliers. ofMap());
}
public > ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Collector super T, A, D> downstream, final Supplier extends M> mapFactory) throws E {
return groupBy(keyMapper, Fn.FN. identity(), downstream, mapFactory);
}
public > ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Try.Function super T, ? extends V, ? extends E> valueMapper, final Collector super V, A, D> downstream) throws E {
return groupBy(keyMapper, valueMapper, downstream, Suppliers. ofMap());
}
public > ExceptionalStream, E> groupBy(final Try.Function super T, ? extends K, ? extends E> keyMapper,
final Try.Function super T, ? extends V, ? extends E> valueMapper, final Collector super V, A, D> downstream,
final Supplier extends M> mapFactory) throws E {
checkArgNotNull(keyMapper, "keyMapper");
checkArgNotNull(valueMapper, "valueMapper");
checkArgNotNull(downstream, "downstream");
checkArgNotNull(mapFactory, "mapFactory");
return newStream(new ExceptionalIterator, E>() {
private Iterator> iter = null;
@Override
public boolean hasNext() throws E {
init();
return iter.hasNext();
}
@Override
public Map.Entry next() throws E {
init();
return iter.next();
}
private void init() throws E {
if (iter == null) {
iter = ExceptionalStream.this.toMap(keyMapper, valueMapper, downstream, mapFactory).entrySet().iterator();
}
}
}, closeHandlers);
}
public ExceptionalStream, E> collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible) {
checkArgNotNull(collapsible, "collapsible");
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 {
if (hasNext == false) {
next = iter.next();
}
final List c = new ArrayList<>();
c.add(next);
while ((hasNext = iter.hasNext())) {
if (collapsible.test(next, (next = iter.next()))) {
c.add(next);
} else {
break;
}
}
return Stream.of(c);
}
}, closeHandlers);
}
public > ExceptionalStream collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible,
final Supplier extends C> supplier) {
checkArgNotNull(collapsible, "collapsible");
checkArgNotNull(supplier, "supplier");
final ExceptionalIterator iter = elements;
return newStream(new ExceptionalIterator() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() throws E {
return hasNext || iter.hasNext();
}
@Override
public C next() throws E {
if (hasNext == false) {
next = iter.next();
}
final C c = supplier.get();
c.add(next);
while ((hasNext = iter.hasNext())) {
if (collapsible.test(next, (next = iter.next()))) {
c.add(next);
} else {
break;
}
}
return c;
}
}, closeHandlers);
}
/**
* Merge series of adjacent elements which satisfy the given predicate using
* the merger function and return a new stream.
*
* Example:
*
*
* Stream.of(new Integer[0]).collapse((a, b) -> a < b, (a, b) -> a + b) => []
* Stream.of(1).collapse((a, b) -> a < b, (a, b) -> a + b) => [1]
* Stream.of(1, 2).collapse((a, b) -> a < b, (a, b) -> a + b) => [3]
* Stream.of(1, 2, 3).collapse((a, b) -> a < b, (a, b) -> a + b) => [6]
* Stream.of(1, 2, 3, 3, 2, 1).collapse((a, b) -> a < b, (a, b) -> a + b) => [6, 3, 2, 1]
*
*
*
*
* This method only run sequentially, even in parallel stream.
*
* @param collapsible
* @param mergeFunction
* @return
*/
public ExceptionalStream collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible,
final Try.BiFunction super T, ? super T, T, ? extends E> mergeFunction) {
checkArgNotNull(collapsible, "collapsible");
checkArgNotNull(mergeFunction, "mergeFunction");
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);
}
public ExceptionalStream collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible, final U init,
final Try.BiFunction op) {
checkArgNotNull(collapsible, "collapsible");
checkArgNotNull(op, "accumulator");
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);
}
public ExceptionalStream collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible, final Try.Supplier supplier,
final Try.BiConsumer super R, ? super T, ? extends E> accumulator) {
checkArgNotNull(collapsible, "collapsible");
checkArgNotNull(supplier, "supplier");
checkArgNotNull(accumulator, "accumulator");
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);
}
public ExceptionalStream collapse(final Try.BiPredicate super T, ? super T, ? extends E> collapsible,
final Collector super T, A, R> collector) {
checkArgNotNull(collapsible, "collapsible");
checkArgNotNull(collector, "collector");
final Supplier supplier = collector.supplier();
final BiConsumer accumulator = collector.accumulator();
final Function finisher = collector.finisher();
final ExceptionalIterator iter = elements;
return newStream(new ExceptionalIterator() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() throws E {
return hasNext || iter.hasNext();
}
@Override
public R next() throws E {
final A container = supplier.get();
accumulator.accept(container, hasNext ? next : (next = iter.next()));
while ((hasNext = iter.hasNext())) {
if (collapsible.test(next, (next = iter.next()))) {
accumulator.accept(container, next);
} else {
break;
}
}
return finisher.apply(container);
}
}, closeHandlers);
}
public ExceptionalStream scan(final Try.BiFunction super T, ? super T, T, E> accumulator) {
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);
}
public ExceptionalStream scan(final U init, final Try.BiFunction accumulator) {
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);
}
public ExceptionalStream scan(final U init, final Try.BiFunction accumulator, final boolean initIncluded) {
if (initIncluded == false) {
return scan(init, accumulator);
}
final ExceptionalIterator iter = elements;
return newStream(new ExceptionalIterator() {
private boolean isFirst = true;
private U res = init;
@Override
public boolean hasNext() throws E {
return isFirst || iter.hasNext();
}
@Override
public U next() throws E {
if (isFirst) {
isFirst = false;
return init;
}
return (res = accumulator.apply(res, iter.next()));
}
}, closeHandlers);
}
public ExceptionalStream prepend(ExceptionalStream s) {
return concat(s, this);
}
public ExceptionalStream append(ExceptionalStream s) {
return concat(this, s);
}
public ExceptionalStream appendIfEmpty(Supplier extends ExceptionalStream> supplier) throws E {
if (elements.hasNext() == false) {
return append(supplier.get());
} else {
return this;
}
}
public ExceptionalStream peek(final Try.Consumer super T, ? extends E> action) {
checkArgNotNull(action, "action");
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, comparator, closeHandlers);
}
public ExceptionalStream, E> split(final int chunkSize) {
return splitToList(chunkSize).map(new Try.Function