com.landawn.abacus.util.stream.AbstractStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-android Show documentation
Show all versions of abacus-android Show documentation
A general programming library in Java
/*
* Copyright (C) 2016 HaiYang Li
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.landawn.abacus.util.stream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import com.landawn.abacus.DataSet;
import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.exception.UncheckedSQLException;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.util.Array;
import com.landawn.abacus.util.BufferedWriter;
import com.landawn.abacus.util.Comparators;
import com.landawn.abacus.util.Fn;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.IOUtil;
import com.landawn.abacus.util.Indexed;
import com.landawn.abacus.util.Iterators;
import com.landawn.abacus.util.Joiner;
import com.landawn.abacus.util.ListMultimap;
import com.landawn.abacus.util.Matrix;
import com.landawn.abacus.util.Multimap;
import com.landawn.abacus.util.Multiset;
import com.landawn.abacus.util.MutableBoolean;
import com.landawn.abacus.util.MutableLong;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.Nth;
import com.landawn.abacus.util.ObjIterator;
import com.landawn.abacus.util.ObjectFactory;
import com.landawn.abacus.util.Optional;
import com.landawn.abacus.util.OptionalDouble;
import com.landawn.abacus.util.Pair;
import com.landawn.abacus.util.Percentage;
import com.landawn.abacus.util.PermutationIterator;
import com.landawn.abacus.util.Try;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.BinaryOperator;
import com.landawn.abacus.util.function.BooleanSupplier;
import com.landawn.abacus.util.function.Consumer;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.function.ToDoubleFunction;
import com.landawn.abacus.util.function.ToIntFunction;
import com.landawn.abacus.util.function.ToLongFunction;
import com.landawn.abacus.util.function.TriFunction;
/**
* This class is a sequential, stateful and immutable stream implementation.
*
* @param
* @since 0.8
*
* @author Haiyang Li
*/
abstract class AbstractStream extends Stream {
AbstractStream(final boolean sorted, final Comparator super T> cmp, final Collection closeHandlers) {
super(sorted, cmp, closeHandlers);
}
@Override
public Stream filter(final U seed, final BiPredicate super T, ? super U> predicate) {
return filter(Fn.p(seed, predicate));
}
@Override
public Stream takeWhile(final U seed, final BiPredicate super T, ? super U> predicate) {
return takeWhile(Fn.p(seed, predicate));
}
@Override
public Stream dropWhile(final U seed, final BiPredicate super T, ? super U> predicate) {
return dropWhile(Fn.p(seed, predicate));
}
@Override
public Stream skip(final long n, final Consumer super T> action) {
N.checkArgNotNegative(n, "n");
if (n == 0) {
return this;
}
final Predicate filter = isParallel() ? new Predicate() {
final AtomicLong cnt = new AtomicLong(n);
@Override
public boolean test(T value) {
return cnt.getAndDecrement() > 0;
}
} : new Predicate() {
final MutableLong cnt = MutableLong.of(n);
@Override
public boolean test(T value) {
return cnt.getAndDecrement() > 0;
}
};
return dropWhile(filter, action);
}
@Override
public Stream peekFirst(final Consumer super T> action) {
final Function super T, ? extends T> mapperForFirst = new Function() {
@Override
public T apply(T t) {
action.accept(t);
return t;
}
};
return mapFirst(mapperForFirst);
}
@Override
public Stream peekLast(final Consumer super T> action) {
final Function super T, ? extends T> mapperForFirst = new Function() {
@Override
public T apply(T t) {
action.accept(t);
return t;
}
};
return mapLast(mapperForFirst);
}
@Override
public Stream removeIf(final Predicate super T> predicate) {
N.checkArgNotNull(predicate);
return filter(new Predicate() {
@Override
public boolean test(T value) {
return predicate.test(value) == false;
}
});
}
@Override
public Stream removeIf(final U seed, final BiPredicate super T, ? super U> predicate) {
N.checkArgNotNull(predicate);
return filter(new Predicate() {
@Override
public boolean test(T value) {
return predicate.test(value, seed) == false;
}
});
}
@Override
public Stream removeIf(final Predicate super T> predicate, final Consumer super T> action) {
N.checkArgNotNull(predicate);
N.checkArgNotNull(action);
return filter(new Predicate() {
@Override
public boolean test(T value) {
if (predicate.test(value)) {
action.accept(value);
return false;
}
return true;
}
});
}
@Override
public Stream removeIf(final U seed, final BiPredicate super T, ? super U> predicate, final Consumer super T> action) {
N.checkArgNotNull(predicate);
N.checkArgNotNull(action);
return filter(new Predicate() {
@Override
public boolean test(T value) {
if (predicate.test(value, seed)) {
action.accept(value);
return false;
}
return true;
}
});
}
@Override
public Stream dropWhile(final Predicate super T> predicate, final Consumer super T> action) {
N.checkArgNotNull(predicate);
N.checkArgNotNull(action);
return dropWhile(new Predicate() {
@Override
public boolean test(T value) {
if (predicate.test(value)) {
action.accept(value);
return true;
}
return false;
}
});
}
@Override
public Stream dropWhile(final U seed, final BiPredicate super T, ? super U> predicate, final Consumer super T> action) {
N.checkArgNotNull(predicate);
N.checkArgNotNull(action);
return dropWhile(new Predicate() {
@Override
public boolean test(T value) {
if (predicate.test(value, seed)) {
action.accept(value);
return true;
}
return false;
}
});
}
@Override
public Stream step(final long step) {
N.checkArgPositive(step, "step");
if (step == 1) {
return this;
}
final long skip = step - 1;
final ObjIteratorEx iter = iteratorEx();
final Iterator iterator = new ObjIteratorEx() {
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public T next() {
final T next = iter.next();
iter.skip(skip);
return next;
}
};
return newStream(iterator, sorted, cmp);
}
@Override
public Stream map(final U seed, final BiFunction super T, ? super U, ? extends R> mapper) {
return map(Fn.f(seed, mapper));
}
// @Override
// public Stream biMap(BiFunction super T, ? super T, ? extends R> mapper) {
// return biMap(mapper, false);
// }
//
// @Override
// public Stream triMap(TriFunction super T, ? super T, ? super T, ? extends R> mapper) {
// return triMap(mapper, false);
// }
@Override
public Stream slidingMap(BiFunction super T, ? super T, R> mapper) {
return slidingMap(mapper, 1);
}
@Override
public Stream slidingMap(BiFunction super T, ? super T, R> mapper, int increment) {
return slidingMap(mapper, increment, false);
}
@Override
public Stream slidingMap(TriFunction super T, ? super T, ? super T, R> mapper) {
return slidingMap(mapper, 1);
}
@Override
public Stream slidingMap(TriFunction super T, ? super T, ? super T, R> mapper, int increment) {
return slidingMap(mapper, increment, false);
}
@Override
public Stream rangeMap(final BiPredicate super T, ? super T> sameRange, final BiFunction super T, ? super T, ? extends U> mapper) {
final Iterator iter = iterator();
return newStream(new ObjIteratorEx() {
private final T NULL = (T) Stream.NONE;
private T left = NULL;
private T right = null;
private T next = null;
@Override
public boolean hasNext() {
return left != NULL || iter.hasNext();
}
@Override
public U next() {
if (left == NULL) {
left = iter.next();
}
right = left;
boolean hasNext = false;
while (iter.hasNext()) {
next = iter.next();
if (sameRange.test(left, next)) {
right = next;
} else {
hasNext = true;
break;
}
}
final U res = mapper.apply(left, right);
left = hasNext ? next : NULL;
return res;
}
}, false, null);
}
@Override
public EntryStream mapToEntry(final Function super T, ? extends Map.Entry> mapper) {
final Function mapper2 = Fn.identity();
if (mapper == mapper2) {
return EntryStream.of((Stream>) this);
}
return EntryStream.of(map(mapper));
}
@Override
public EntryStream mapToEntry(final Function super T, K> keyMapper, final Function super T, V> valueMapper) {
final Function> mapper = new Function>() {
@Override
public Entry apply(T t) {
return new SimpleImmutableEntry<>(keyMapper.apply(t), valueMapper.apply(t));
}
};
return mapToEntry(mapper);
}
@Override
public Stream flatMap(final U seed, final BiFunction super T, ? super U, ? extends Stream extends R>> mapper) {
return flatMap(new Function>() {
@Override
public Stream extends R> apply(T t) {
return mapper.apply(t, seed);
}
});
}
@Override
public Stream flattMap(final Function super T, ? extends Collection extends R>> mapper) {
return flatMap(new Function>() {
@Override
public Stream extends R> apply(T t) {
return Stream.of(mapper.apply(t));
}
});
}
@Override
public Stream flattMap(final U seed, final BiFunction super T, ? super U, ? extends Collection extends R>> mapper) {
return flatMap(new Function>() {
@Override
public Stream extends R> apply(T t) {
return Stream.of(mapper.apply(t, seed));
}
});
}
@Override
public Stream flatMapp(final Function super T, R[]> mapper) {
return flatMap(new Function>() {
@Override
public Stream extends R> apply(T t) {
return Stream.of(mapper.apply(t));
}
});
}
@Override
public Stream flatMapp(final U seed, final BiFunction super T, ? super U, R[]> mapper) {
return flatMap(new Function>() {
@Override
public Stream extends R> apply(T t) {
return Stream.of(mapper.apply(t, seed));
}
});
}
@Override
public EntryStream flatMapToEntry(final Function super T, ? extends Stream extends Map.Entry>> mapper) {
return EntryStream.of(flatMap(mapper));
}
@Override
@ParallelSupported
public EntryStream flattMapToEntry(final Function super T, ? extends Map> mapper) {
final Function super T, ? extends Stream extends Entry>> mapper2 = new Function>>() {
@Override
public Stream extends Entry> apply(T t) {
return Stream.of(mapper.apply(t));
}
};
return flatMapToEntry(mapper2);
}
@Override
@ParallelSupported
public EntryStream flatMappToEntry(final Function super T, ? extends EntryStream> mapper) {
final Function super T, ? extends Stream extends Entry>> mapper2 = new Function>>() {
@Override
public Stream extends Entry> apply(T t) {
return mapper.apply(t).entries();
}
};
return flatMapToEntry(mapper2);
}
// @Override
// public EntryStream flattMapToEntry(final Function super T, ? extends Collection extends V>> flatValueMapper) {
// final Function>> flatEntryMapper = new Function>>() {
// @Override
// public Stream> apply(final T t) {
// final Function> entryMapper = new Function>() {
// @Override
// public Entry apply(V v) {
// return new SimpleImmutableEntry<>(t, v);
// }
// };
//
// return Stream.of(flatValueMapper.apply(t)).map(entryMapper);
// }
// };
//
// return flatMapToEntry(flatEntryMapper);
// }
@Override
@SuppressWarnings("rawtypes")
public Stream sortedBy(final Function super T, ? extends Comparable> keyExtractor) {
final Comparator super T> comparator = new Comparator() {
@Override
public int compare(T o1, T o2) {
return N.compare(keyExtractor.apply(o1), keyExtractor.apply(o2));
}
};
return sorted(comparator);
}
@Override
public Stream sortedByInt(final ToIntFunction super T> keyExtractor) {
final Comparator super T> comparator = Comparators.comparingInt(keyExtractor);
return sorted(comparator);
}
@Override
public Stream sortedByLong(final ToLongFunction super T> keyExtractor) {
final Comparator super T> comparator = Comparators.comparingLong(keyExtractor);
return sorted(comparator);
}
@Override
public Stream sortedByDouble(final ToDoubleFunction super T> keyExtractor) {
final Comparator super T> comparator = Comparators.comparingDouble(keyExtractor);
return sorted(comparator);
}
@Override
public Stream> split(final int size) {
return splitToList(size).map(new Function, Stream>() {
@Override
public Stream apply(List t) {
return new ArrayStream<>(toArray(t), 0, t.size(), sorted, cmp, null);
}
});
}
@Override
public Stream> splitToList(final int size) {
return split(size, Fn.Factory. ofList());
}
@Override
public Stream> splitToSet(final int size) {
return split(size, Fn.Factory. ofSet());
}
@Override
public Stream> split(final Predicate super T> predicate) {
return splitToList(predicate).map(new Function, Stream>() {
@Override
public Stream apply(List t) {
return new ArrayStream<>(toArray(t), 0, t.size(), sorted, cmp, null);
}
});
}
@Override
public Stream> splitToList(final Predicate super T> predicate) {
return split(predicate, Suppliers. ofList());
}
@Override
public Stream> splitToSet(final Predicate super T> predicate) {
return split(predicate, Suppliers. ofSet());
}
@Override
public > Stream split(final Predicate super T> predicate, final Supplier collectionSupplier) {
final BiPredicate predicate2 = new BiPredicate() {
@Override
public boolean test(T t, Object u) {
return predicate.test(t);
}
};
return split(null, predicate2, null, collectionSupplier);
}
@Override
public Stream> split(final U seed, final BiPredicate super T, ? super U> predicate, final Consumer super U> seedUpdate) {
return splitToList(seed, predicate, seedUpdate).map(new Function, Stream>() {
@Override
public Stream apply(List t) {
return new ArrayStream<>(toArray(t), 0, t.size(), sorted, cmp, null);
}
});
}
@Override
public Stream> splitToList(final U seed, final BiPredicate super T, ? super U> predicate, final Consumer super U> seedUpdate) {
return split(seed, predicate, seedUpdate, Suppliers. ofList());
}
@Override
public Stream> splitToSet(final U seed, final BiPredicate super T, ? super U> predicate, final Consumer super U> seedUpdate) {
return split(seed, predicate, seedUpdate, Suppliers. ofSet());
}
@Override
public Stream> sliding(final int windowSize, final int increment) {
return slidingToList(windowSize, increment).map(new Function, Stream>() {
@Override
public Stream apply(List t) {
return new ArrayStream<>(toArray(t), 0, t.size(), sorted, cmp, null);
}
});
}
@Override
public Stream> slidingToList(final int windowSize, final int increment) {
return sliding(windowSize, increment, Fn.Factory. ofList());
}
@Override
public > Stream sliding(final int windowSize, IntFunction collectionSupplier) {
return sliding(windowSize, 1, collectionSupplier);
}
@Override
public Stream collapse(final BiPredicate super T, ? super T> collapsible, final BiFunction super T, ? super T, T> mergeFunction) {
final ObjIteratorEx iter = iteratorEx();
return newStream(new ObjIteratorEx() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() {
return hasNext || iter.hasNext();
}
@Override
public T next() {
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;
}
}, false, null);
}
@Override
public Stream collapse(final BiPredicate super T, ? super T> collapsible, final Supplier supplier, final BiConsumer accumulator) {
final ObjIteratorEx iter = iteratorEx();
return newStream(new ObjIteratorEx() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() {
return hasNext || iter.hasNext();
}
@Override
public R next() {
final R res = supplier.get();
accumulator.accept(res, hasNext ? next : (next = iter.next()));
while ((hasNext = iter.hasNext())) {
if (collapsible.test(next, (next = iter.next()))) {
accumulator.accept(res, next);
} else {
break;
}
}
return res;
}
}, false, null);
}
@Override
public Stream collapse(final BiPredicate super T, ? super T> collapsible, final Collector super T, A, R> collector) {
final Supplier supplier = collector.supplier();
final BiConsumer accumulator = collector.accumulator();
final Function finisher = collector.finisher();
final ObjIteratorEx iter = iteratorEx();
return newStream(new ObjIteratorEx() {
private boolean hasNext = false;
private T next = null;
@Override
public boolean hasNext() {
return hasNext || iter.hasNext();
}
@Override
public R next() {
final A c = supplier.get();
accumulator.accept(c, hasNext ? next : (next = iter.next()));
while ((hasNext = iter.hasNext())) {
if (collapsible.test(next, (next = iter.next()))) {
accumulator.accept(c, next);
} else {
break;
}
}
return finisher.apply(c);
}
}, false, null);
}
@Override
public Stream scan(final BiFunction super T, ? super T, T> accumulator) {
final ObjIteratorEx iter = iteratorEx();
return newStream(new ObjIteratorEx() {
private T res = null;
private boolean isFirst = true;
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public T next() {
if (isFirst) {
isFirst = false;
return (res = iter.next());
} else {
return (res = accumulator.apply(res, iter.next()));
}
}
}, false, null);
}
@Override
public Stream scan(final R seed, final BiFunction super R, ? super T, R> accumulator) {
final ObjIteratorEx iter = iteratorEx();
return newStream(new ObjIteratorEx() {
private R res = seed;
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public R next() {
return (res = accumulator.apply(res, iter.next()));
}
}, false, null);
}
@Override
public Stream intersperse(final T delimiter) {
return newStream(new ObjIteratorEx() {
private final Iterator iter = iterator();
private boolean toInsert = false;
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public T next() {
if (hasNext() == false) {
throw new NoSuchElementException();
}
if (toInsert) {
toInsert = false;
return delimiter;
} else {
final T res = iter.next();
toInsert = true;
return res;
}
}
}, false, null);
}
@Override
public void forEachPair(final Try.BiConsumer super T, ? super T, E> action) throws E {
forEachPair(action, 1);
}
@Override
public void forEachTriple(final Try.TriConsumer super T, ? super T, ? super T, E> action) throws E {
forEachTriple(action, 1);
}
@Override
public Stream>> groupBy(final Function super T, ? extends K> classifier) {
return groupBy(classifier, Fn. identity());
}
@Override
public Stream>> groupBy(final Function super T, ? extends K> classifier, Supplier extends Map>> mapFactory) {
return groupBy(classifier, Fn. identity(), mapFactory);
}
@Override
public Stream>> groupBy(Function super T, ? extends K> classifier, Function super T, ? extends U> valueMapper) {
final Collector> downstream = Collectors.mapping(valueMapper, Collectors. toList());
return groupBy(classifier, downstream);
}
@Override
public Stream>> groupBy(Function super T, ? extends K> classifier, Function super T, ? extends U> valueMapper,
Supplier extends Map>> mapFactory) {
final Collector> downstream = Collectors.mapping(valueMapper, Collectors. toList());
return groupBy(classifier, downstream, mapFactory);
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, Collector super T, A, D> downstream) {
return groupBy(classifier, downstream, Fn.Suppliers. ofMap());
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, final Collector super T, A, D> downstream,
final Supplier extends Map> mapFactory) {
return newStream(new ObjIteratorEx>() {
private Iterator> iter = null;
@Override
public boolean hasNext() {
init();
return iter.hasNext();
}
@Override
public Entry next() {
init();
return iter.next();
}
private void init() {
if (iter == null) {
iter = AbstractStream.this.toMap(classifier, downstream, mapFactory).entrySet().iterator();
}
}
}, false, null);
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, final Function super T, ? extends U> valueMapper,
Collector super U, A, D> downstream) {
return groupBy(classifier, valueMapper, downstream, Fn.Suppliers. ofMap());
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, final Function super T, ? extends U> valueMapper,
Collector super U, A, D> downstream, Supplier extends Map> mapFactory) {
final Collector downstream2 = Collectors.mapping(valueMapper, downstream);
return groupBy(classifier, downstream2, mapFactory);
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, final Function super T, ? extends U> valueMapper,
BinaryOperator mergeFunction) {
return groupBy(classifier, valueMapper, mergeFunction, Fn.Suppliers. ofMap());
}
@Override
public Stream> groupBy(final Function super T, ? extends K> classifier, final Function super T, ? extends V> valueMapper,
final BinaryOperator mergeFunction, final Supplier extends Map> mapFactory) {
return newStream(new ObjIteratorEx>() {
private Iterator> iter = null;
@Override
public boolean hasNext() {
init();
return iter.hasNext();
}
@Override
public Entry next() {
init();
return iter.next();
}
private void init() {
if (iter == null) {
iter = AbstractStream.this.toMap(classifier, valueMapper, mergeFunction, mapFactory).entrySet().iterator();
}
}
}, false, null);
}
@Override
public Stream>> partitionBy(Predicate super T> predicate) {
return partitionBy(predicate, Collectors. toList());
}
@Override
public Stream> partitionBy(final Predicate super T> predicate, final Collector super T, A, D> downstream) {
return newStream(new ObjIteratorEx>() {
private Iterator> iter = null;
@Override
public boolean hasNext() {
init();
return iter.hasNext();
}
@Override
public Entry next() {
init();
return iter.next();
}
private void init() {
if (iter == null) {
iter = AbstractStream.this.partitionTo(predicate, downstream).entrySet().iterator();
}
}
}, false, null);
}
@Override
public EntryStream> partitionByToEntry(Predicate super T> predicate) {
return partitionByToEntry(predicate, Collectors. toList());
}
@Override
public EntryStream partitionByToEntry(Predicate super T> predicate, Collector super T, A, D> downstream) {
final Function, Map.Entry> mapper = Fn.identity();
return partitionBy(predicate, downstream).mapToEntry(mapper);
}
@Override
public EntryStream> groupByToEntry(Function super T, ? extends K> classifier) {
return groupByToEntry(classifier, Fn. identity());
}
@Override
public EntryStream> groupByToEntry(Function super T, ? extends K> classifier, Supplier extends Map>> mapFactory) {
return groupByToEntry(classifier, Fn. identity(), mapFactory);
}
@Override
public EntryStream> groupByToEntry(Function super T, ? extends K> classifier, Function super T, ? extends U> valueMapper) {
return groupByToEntry(classifier, valueMapper, Fn.Suppliers.> ofMap());
}
@Override
public EntryStream> groupByToEntry(Function super T, ? extends K> classifier, Function super T, ? extends U> valueMapper,
Supplier extends Map>> mapFactory) {
final Function>, Map.Entry>> mapper = Fn.identity();
return groupBy(classifier, valueMapper, mapFactory).mapToEntry(mapper);
}
@Override
public