|
|
@@ -1,442 +1,448 @@
|
|
|
-/*
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
- * @copyright Ranides Atterwim
|
|
|
- * @license WTFPL
|
|
|
- * @url http://ranides.net/projects/assira
|
|
|
- */
|
|
|
-package net.ranides.assira.collection.query;
|
|
|
-
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.Comparator;
|
|
|
-import java.util.Iterator;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.NoSuchElementException;
|
|
|
-import java.util.Set;
|
|
|
-import java.util.Spliterator;
|
|
|
-import java.util.function.BinaryOperator;
|
|
|
-import java.util.function.Consumer;
|
|
|
-import java.util.function.Function;
|
|
|
-import java.util.function.IntFunction;
|
|
|
-import java.util.function.Predicate;
|
|
|
-import java.util.function.Supplier;
|
|
|
-import java.util.stream.Collector;
|
|
|
-import java.util.stream.Collectors;
|
|
|
-import java.util.stream.Stream;
|
|
|
-import java.util.stream.StreamSupport;
|
|
|
-import net.ranides.assira.collection.HashFunction;
|
|
|
-import net.ranides.assira.collection.arrays.ArraySort;
|
|
|
-import net.ranides.assira.collection.arrays.ArrayUtils;
|
|
|
-import net.ranides.assira.collection.iterators.IteratorUtils;
|
|
|
-import net.ranides.assira.collection.sets.CustomSet;
|
|
|
-import net.ranides.assira.collection.sets.HashSet;
|
|
|
-import net.ranides.assira.collection.sets.RBTreeSet;
|
|
|
-import net.ranides.assira.functional.Fold;
|
|
|
-
|
|
|
-/**
|
|
|
- *
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
- */
|
|
|
-abstract class CQueryAbstract<T> implements CQuery<T> {
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <A, R> R collect(Collector<? super T, A, R> collector) {
|
|
|
- return stream().collect(collector);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final Object[] array() {
|
|
|
- return stream().toArray();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <A> A[] array(IntFunction<A[]> generator) {
|
|
|
- return stream().toArray(generator);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final List<T> list() {
|
|
|
- return stream().collect(Collectors.toList());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final Set<T> set() {
|
|
|
- return stream().collect(Collectors.toSet());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> limit(Predicate<? super T> p) {
|
|
|
- return new CQIterable<>(() -> IteratorUtils.limit(iterator(), p));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> limit(int n) {
|
|
|
- return new CQBounded<>(this, 0, n);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> skip(int n) {
|
|
|
- return new CQBounded<>(this, n, Integer.MAX_VALUE);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> slice(int begin, int end) {
|
|
|
- return new CQBounded<>(this, begin, end-begin);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <K> Map<K, T> group(Function<? super T, ? extends K> key) {
|
|
|
- return stream().collect(Collectors.toMap(key, v -> v));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <K, V> Map<K, V> group(Function<? super T, ? extends K> key, Function<? super T, ? extends V> value) {
|
|
|
- return stream().collect(Collectors.toMap(key, value));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final boolean isEmpty() {
|
|
|
- return !iterator().hasNext();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> filter(Predicate<? super T> p) {
|
|
|
- return new CQIterable<>(() -> IteratorUtils.filter(iterator(), p));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <R> CQuery<R> map(Function<? super T, ? extends R> f) {
|
|
|
- return new CQIterable<>(() -> IteratorUtils.map(iterator(), f));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f) {
|
|
|
- return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public <R> CQuery<R> split(Function<? super T, R[]> f) {
|
|
|
- return unfold(v -> CQueryBuilder.fromArray(f.apply(v)) );
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T fold(T identity, BinaryOperator<T> accumulator) {
|
|
|
- Iterator<T> i = iterator();
|
|
|
- return i.hasNext() ? Fold.apply(i, accumulator::apply) : identity;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T fold(BinaryOperator<T> accumulator) {
|
|
|
- return fold(null, accumulator);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T min(Comparator<? super T> cmp) {
|
|
|
- return fold((a, b) -> cmp.compare(a, b) < 0 ? a : b);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T max(Comparator<? super T> cmp) {
|
|
|
- return fold((a, b) -> cmp.compare(a, b) > 0 ? a : b);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T first() {
|
|
|
- return IteratorUtils.first(iterator());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final T last() {
|
|
|
- return IteratorUtils.last(iterator());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> distinct() {
|
|
|
- return new CQCollection<>(() -> new HashSet<>(iterator()));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> distinct(HashFunction<T> eq) {
|
|
|
- return new CQCollection<>(() -> new CustomSet<>(iterator(), eq));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> distinct(Comparator<? super T> cmp) {
|
|
|
- return new CQCollection<>(() -> new RBTreeSet<>(iterator(), cmp));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> sort() {
|
|
|
- return new CQCollection<>(() -> {
|
|
|
- List<T> list = list();
|
|
|
- ArraySort.mergeSort(list);
|
|
|
- return list;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final CQuery<T> sort(Comparator<? super T> cmp) {
|
|
|
- return new CQCollection<>(() -> {
|
|
|
- List<T> list = list();
|
|
|
- ArraySort.mergeSort(list, cmp);
|
|
|
- return list;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final void each(Consumer<? super T> consumer) {
|
|
|
- stream().forEach(consumer);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void into(Collection<? super T> collection) {
|
|
|
- stream().forEach(collection::add);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final boolean matchAny(Predicate<? super T> predicate) {
|
|
|
- return stream().anyMatch(predicate);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final boolean matchAll(Predicate<? super T> predicate) {
|
|
|
- return stream().allMatch(predicate);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public final boolean matchNone(Predicate<? super T> predicate) {
|
|
|
- return stream().noneMatch(predicate);
|
|
|
- }
|
|
|
-
|
|
|
- protected static class CQCollection<T> extends CQueryAbstract<T> {
|
|
|
-
|
|
|
- private final Supplier<Collection<T>> source;
|
|
|
-
|
|
|
- public CQCollection(Supplier<Collection<T>> source) {
|
|
|
- this.source = source;
|
|
|
- }
|
|
|
-
|
|
|
- public CQCollection(Collection<T> source) {
|
|
|
- this(() -> source);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Iterator<T> iterator() {
|
|
|
- return source.get().iterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Spliterator<T> spliterator() {
|
|
|
- return source.get().spliterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Stream<T> stream() {
|
|
|
- return source.get().stream();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int size() {
|
|
|
- return source.get().size();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- protected static class CQArray<T> extends CQueryAbstract<T> {
|
|
|
-
|
|
|
- private final Supplier<T[]> source;
|
|
|
- private final int offset;
|
|
|
- private final int limit;
|
|
|
-
|
|
|
- public CQArray(Supplier<T[]> source) {
|
|
|
- this(source, 0, Integer.MAX_VALUE);
|
|
|
- }
|
|
|
-
|
|
|
- public CQArray(Supplier<T[]> source, int offset, int limit) {
|
|
|
- this.source = source;
|
|
|
- this.offset = offset;
|
|
|
- this.limit = limit;
|
|
|
- }
|
|
|
-
|
|
|
- public CQArray(T[] source) {
|
|
|
- this(source, 0, source.length);
|
|
|
- }
|
|
|
-
|
|
|
- public CQArray(T[] source, int offset, int limit) {
|
|
|
- this(() -> source, offset,limit);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Iterator<T> iterator() {
|
|
|
- T[] array = source.get();
|
|
|
- return ArrayUtils.iterator(array, offset, offset + Math.min(array.length,limit));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Spliterator<T> spliterator() {
|
|
|
- T[] array = source.get();
|
|
|
- return Arrays.spliterator(array, offset, offset + Math.min(array.length,limit));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Stream<T> stream() {
|
|
|
- T[] array = source.get();
|
|
|
- return Arrays.stream(array, offset, offset + Math.min(array.length,limit));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int size() {
|
|
|
- return Math.min(limit, source.get().length);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> limit(int n) {
|
|
|
- return new CQArray<>(source, offset, Math.min(limit, n));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> skip(int n) {
|
|
|
- return new CQArray<>(source, offset+n, limit);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- protected static class CQIterable<T> extends CQueryAbstract<T> {
|
|
|
-
|
|
|
- private final Supplier<Iterable<T>> source;
|
|
|
-
|
|
|
- public CQIterable(Supplier<Iterable<T>> source) {
|
|
|
- this.source = source;
|
|
|
- }
|
|
|
-
|
|
|
- public CQIterable(Iterable<T> source) {
|
|
|
- this(() -> source);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Iterator<T> iterator() {
|
|
|
- return source.get().iterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Spliterator<T> spliterator() {
|
|
|
- return source.get().spliterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Stream<T> stream() {
|
|
|
- return StreamSupport.stream(source.get().spliterator(), false);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int size() {
|
|
|
- return IteratorUtils.size(source.get().iterator());
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- protected static class CQQuery<T> extends CQueryAbstract<T> {
|
|
|
-
|
|
|
- private final Supplier<CQuery<T>> source;
|
|
|
-
|
|
|
- public CQQuery(Supplier<CQuery<T>> source) {
|
|
|
- this.source = source;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Iterator<T> iterator() {
|
|
|
- return source.get().iterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Spliterator<T> spliterator() {
|
|
|
- return source.get().spliterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Stream<T> stream() {
|
|
|
- return source.get().stream();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int size() {
|
|
|
- return source.get().size();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- protected static class CQBounded<T> extends CQueryAbstract<T> {
|
|
|
-
|
|
|
- private final CQuery<T> stream;
|
|
|
- private final int begin;
|
|
|
- private final int size;
|
|
|
-
|
|
|
- public CQBounded(CQuery<T> stream, int begin, int size) {
|
|
|
- this.stream = stream;
|
|
|
- this.begin = begin;
|
|
|
- this.size = size;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> limit(int n) {
|
|
|
- return new CQBounded<>(stream, begin, Math.min(n, size));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CQuery<T> skip(int n) {
|
|
|
- return new CQBounded<>(stream, begin+n, size);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Iterator<T> iterator() {
|
|
|
- Iterator<T> i = stream.iterator();
|
|
|
- IteratorUtils.next(i, begin);
|
|
|
- return new BIterator<>(i, size);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Spliterator<T> spliterator() {
|
|
|
- return stream().spliterator();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Stream<T> stream() {
|
|
|
- return stream.stream().skip(begin).limit(size);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int size() {
|
|
|
- return Math.min(stream.size(), size);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private static final class BIterator<T> implements Iterator<T> {
|
|
|
-
|
|
|
- private final Iterator<T> src;
|
|
|
- private final int limit;
|
|
|
- private int count;
|
|
|
-
|
|
|
- public BIterator(Iterator<T> src, int limit) {
|
|
|
- this.src = src;
|
|
|
- this.limit = limit;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean hasNext() {
|
|
|
- return count<limit && src.hasNext();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public T next() {
|
|
|
- if(count>=limit) {
|
|
|
- throw new NoSuchElementException();
|
|
|
- }
|
|
|
- count++;
|
|
|
- return src.next();
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.collection.query;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.NoSuchElementException;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.Spliterator;
|
|
|
+import java.util.function.BinaryOperator;
|
|
|
+import java.util.function.Consumer;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.function.IntFunction;
|
|
|
+import java.util.function.Predicate;
|
|
|
+import java.util.function.Supplier;
|
|
|
+import java.util.stream.Collector;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
+import java.util.stream.StreamSupport;
|
|
|
+import net.ranides.assira.collection.HashFunction;
|
|
|
+import net.ranides.assira.collection.arrays.ArraySort;
|
|
|
+import net.ranides.assira.collection.arrays.ArrayUtils;
|
|
|
+import net.ranides.assira.collection.iterators.IteratorUtils;
|
|
|
+import net.ranides.assira.collection.sets.CustomSet;
|
|
|
+import net.ranides.assira.collection.sets.HashSet;
|
|
|
+import net.ranides.assira.collection.sets.RBTreeSet;
|
|
|
+import net.ranides.assira.functional.EachFunction;
|
|
|
+import net.ranides.assira.functional.Fold;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ */
|
|
|
+abstract class CQueryAbstract<T> implements CQuery<T> {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <A, R> R collect(Collector<? super T, A, R> collector) {
|
|
|
+ return stream().collect(collector);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final Object[] array() {
|
|
|
+ return stream().toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <A> A[] array(IntFunction<A[]> generator) {
|
|
|
+ return stream().toArray(generator);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final List<T> list() {
|
|
|
+ return stream().collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final Set<T> set() {
|
|
|
+ return stream().collect(Collectors.toSet());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> limit(Predicate<? super T> p) {
|
|
|
+ return new CQIterable<>(() -> IteratorUtils.limit(iterator(), p));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> limit(int n) {
|
|
|
+ return new CQBounded<>(this, 0, n);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> skip(int n) {
|
|
|
+ return new CQBounded<>(this, n, Integer.MAX_VALUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> slice(int begin, int end) {
|
|
|
+ return new CQBounded<>(this, begin, end-begin);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <K> Map<K, T> group(Function<? super T, ? extends K> key) {
|
|
|
+ return stream().collect(Collectors.toMap(key, v -> v));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <K, V> Map<K, V> group(Function<? super T, ? extends K> key, Function<? super T, ? extends V> value) {
|
|
|
+ return stream().collect(Collectors.toMap(key, value));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean isEmpty() {
|
|
|
+ return !iterator().hasNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> filter(Predicate<? super T> p) {
|
|
|
+ return new CQIterable<>(() -> IteratorUtils.filter(iterator(), p));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <R> CQuery<R> map(Function<? super T, ? extends R> f) {
|
|
|
+ return new CQIterable<>(() -> IteratorUtils.map(iterator(), f));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <R> CQuery<R> imap(EachFunction<? super T, ? extends R> f) {
|
|
|
+ return new CQIterable<>(() -> IteratorUtils.imap(iterator(), f));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f) {
|
|
|
+ return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public <R> CQuery<R> split(Function<? super T, R[]> f) {
|
|
|
+ return unfold(v -> CQueryBuilder.fromArray(f.apply(v)) );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T fold(T identity, BinaryOperator<T> accumulator) {
|
|
|
+ Iterator<T> i = iterator();
|
|
|
+ return i.hasNext() ? Fold.apply(i, accumulator::apply) : identity;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T fold(BinaryOperator<T> accumulator) {
|
|
|
+ return fold(null, accumulator);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T min(Comparator<? super T> cmp) {
|
|
|
+ return fold((a, b) -> cmp.compare(a, b) < 0 ? a : b);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T max(Comparator<? super T> cmp) {
|
|
|
+ return fold((a, b) -> cmp.compare(a, b) > 0 ? a : b);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T first() {
|
|
|
+ return IteratorUtils.first(iterator());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final T last() {
|
|
|
+ return IteratorUtils.last(iterator());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> distinct() {
|
|
|
+ return new CQCollection<>(() -> new HashSet<>(iterator()));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> distinct(HashFunction<T> eq) {
|
|
|
+ return new CQCollection<>(() -> new CustomSet<>(iterator(), eq));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> distinct(Comparator<? super T> cmp) {
|
|
|
+ return new CQCollection<>(() -> new RBTreeSet<>(iterator(), cmp));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> sort() {
|
|
|
+ return new CQCollection<>(() -> {
|
|
|
+ List<T> list = list();
|
|
|
+ ArraySort.mergeSort(list);
|
|
|
+ return list;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final CQuery<T> sort(Comparator<? super T> cmp) {
|
|
|
+ return new CQCollection<>(() -> {
|
|
|
+ List<T> list = list();
|
|
|
+ ArraySort.mergeSort(list, cmp);
|
|
|
+ return list;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final void each(Consumer<? super T> consumer) {
|
|
|
+ stream().forEach(consumer);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void into(Collection<? super T> collection) {
|
|
|
+ stream().forEach(collection::add);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean matchAny(Predicate<? super T> predicate) {
|
|
|
+ return stream().anyMatch(predicate);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean matchAll(Predicate<? super T> predicate) {
|
|
|
+ return stream().allMatch(predicate);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean matchNone(Predicate<? super T> predicate) {
|
|
|
+ return stream().noneMatch(predicate);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static class CQCollection<T> extends CQueryAbstract<T> {
|
|
|
+
|
|
|
+ private final Supplier<Collection<T>> source;
|
|
|
+
|
|
|
+ public CQCollection(Supplier<Collection<T>> source) {
|
|
|
+ this.source = source;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CQCollection(Collection<T> source) {
|
|
|
+ this(() -> source);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ return source.get().iterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Spliterator<T> spliterator() {
|
|
|
+ return source.get().spliterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Stream<T> stream() {
|
|
|
+ return source.get().stream();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return source.get().size();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static class CQArray<T> extends CQueryAbstract<T> {
|
|
|
+
|
|
|
+ private final Supplier<T[]> source;
|
|
|
+ private final int offset;
|
|
|
+ private final int limit;
|
|
|
+
|
|
|
+ public CQArray(Supplier<T[]> source) {
|
|
|
+ this(source, 0, Integer.MAX_VALUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ public CQArray(Supplier<T[]> source, int offset, int limit) {
|
|
|
+ this.source = source;
|
|
|
+ this.offset = offset;
|
|
|
+ this.limit = limit;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CQArray(T[] source) {
|
|
|
+ this(source, 0, source.length);
|
|
|
+ }
|
|
|
+
|
|
|
+ public CQArray(T[] source, int offset, int limit) {
|
|
|
+ this(() -> source, offset,limit);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ T[] array = source.get();
|
|
|
+ return ArrayUtils.iterator(array, offset, Math.min(array.length,offset+limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Spliterator<T> spliterator() {
|
|
|
+ T[] array = source.get();
|
|
|
+ return Arrays.spliterator(array, offset, Math.min(array.length,offset+limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Stream<T> stream() {
|
|
|
+ T[] array = source.get();
|
|
|
+ return Arrays.stream(array, offset, Math.min(array.length,offset+limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return Math.min(limit, source.get().length);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> limit(int n) {
|
|
|
+ return new CQArray<>(source, offset, Math.min(limit, n));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> skip(int n) {
|
|
|
+ return new CQArray<>(source, offset+n, limit);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static class CQIterable<T> extends CQueryAbstract<T> {
|
|
|
+
|
|
|
+ private final Supplier<Iterable<T>> source;
|
|
|
+
|
|
|
+ public CQIterable(Supplier<Iterable<T>> source) {
|
|
|
+ this.source = source;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CQIterable(Iterable<T> source) {
|
|
|
+ this(() -> source);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ return source.get().iterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Spliterator<T> spliterator() {
|
|
|
+ return source.get().spliterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Stream<T> stream() {
|
|
|
+ return StreamSupport.stream(source.get().spliterator(), false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return IteratorUtils.size(source.get().iterator());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static class CQQuery<T> extends CQueryAbstract<T> {
|
|
|
+
|
|
|
+ private final Supplier<CQuery<T>> source;
|
|
|
+
|
|
|
+ public CQQuery(Supplier<CQuery<T>> source) {
|
|
|
+ this.source = source;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ return source.get().iterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Spliterator<T> spliterator() {
|
|
|
+ return source.get().spliterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Stream<T> stream() {
|
|
|
+ return source.get().stream();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return source.get().size();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static class CQBounded<T> extends CQueryAbstract<T> {
|
|
|
+
|
|
|
+ private final CQuery<T> stream;
|
|
|
+ private final int begin;
|
|
|
+ private final int size;
|
|
|
+
|
|
|
+ public CQBounded(CQuery<T> stream, int begin, int size) {
|
|
|
+ this.stream = stream;
|
|
|
+ this.begin = begin;
|
|
|
+ this.size = size;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> limit(int n) {
|
|
|
+ return new CQBounded<>(stream, begin, Math.min(n, size));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CQuery<T> skip(int n) {
|
|
|
+ return new CQBounded<>(stream, begin+n, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<T> iterator() {
|
|
|
+ Iterator<T> i = stream.iterator();
|
|
|
+ IteratorUtils.next(i, begin);
|
|
|
+ return new BIterator<>(i, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Spliterator<T> spliterator() {
|
|
|
+ return stream().spliterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Stream<T> stream() {
|
|
|
+ return stream.stream().skip(begin).limit(size);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return Math.min(stream.size(), size);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final class BIterator<T> implements Iterator<T> {
|
|
|
+
|
|
|
+ private final Iterator<T> src;
|
|
|
+ private final int limit;
|
|
|
+ private int count;
|
|
|
+
|
|
|
+ public BIterator(Iterator<T> src, int limit) {
|
|
|
+ this.src = src;
|
|
|
+ this.limit = limit;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasNext() {
|
|
|
+ return count<limit && src.hasNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T next() {
|
|
|
+ if(count>=limit) {
|
|
|
+ throw new NoSuchElementException();
|
|
|
+ }
|
|
|
+ count++;
|
|
|
+ return src.next();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|