org.rx.common.NQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxlib Show documentation
Show all versions of rxlib Show documentation
A set of utilities for Java
package org.rx.common;
import com.google.common.collect.Streams;
import org.rx.annotation.ErrorCode;
import org.rx.beans.Tuple;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static org.rx.common.Contract.*;
/**
* https://msdn.microsoft.com/en-us/library/bb738550(v=vs.110).aspx
*
* @param
*/
public final class NQuery implements Iterable {
@FunctionalInterface
public interface IndexSelector {
TR apply(T t, int index);
}
@FunctionalInterface
public interface IndexPredicate {
boolean test(T t, int index);
default IndexPredicate negate() {
return (t, i) -> !test(t, i);
}
}
//region of
private static final Comparator NaturalOrder = Comparator.naturalOrder(), ReverseOrder = Comparator.reverseOrder();
public static NQuery of(T... set) {
return of(Arrays.asList(set));
}
public static NQuery of(Stream stream) {
require(stream);
return of(stream.collect(Collectors.toList()), stream.isParallel());
}
public static NQuery of(Collection set) {
return of(set, false);
}
public static NQuery of(Collection set, boolean isParallel) {
require(set);
return new NQuery<>(set, isParallel);
}
//endregion
//region Member
private Collection current;
private boolean isParallel;
public Stream stream() {
return isParallel ? current.parallelStream() : current.stream();
}
private NQuery(Collection set, boolean isParallel) {
this.current = set;
this.isParallel = isParallel;
}
@Override
public Iterator iterator() {
return stream().iterator();
}
private List newList() {
int count = count();
return isParallel ? Collections.synchronizedList(new ArrayList<>(count)) : new ArrayList<>(count);
}
private Set newSet() {
int count = count();
return isParallel ? Collections.synchronizedSet(new LinkedHashSet<>(count)) : new LinkedHashSet<>(count);
}
private Map newMap() {
int count = count();
return isParallel ? Collections.synchronizedMap(new LinkedHashMap<>(count)) : new LinkedHashMap<>(count);
}
private Stream newStream(Collection set) {
return isParallel ? set.parallelStream() : set.stream();
}
private NQuery me(Collection set) {
return of(set, isParallel);
}
private NQuery me(Stream stream) {
return me(stream.collect(Collectors.toList()));
}
private NQuery me(EachFunc func) {
return me(stream(), func);
}
private NQuery me(Stream stream, EachFunc func) {
boolean isParallel = stream.isParallel();
Spliterator spliterator = stream.spliterator();
return me(StreamSupport.stream(
new Spliterators.AbstractSpliterator (spliterator.estimateSize(), spliterator.characteristics()) {
AtomicBoolean breaker = new AtomicBoolean();
AtomicInteger counter = new AtomicInteger();
@Override
public boolean tryAdvance(Consumer action) {
return spliterator.tryAdvance(p -> {
int flags = func.each(p, counter.getAndIncrement());
if ((flags & EachFunc.Accept) == EachFunc.Accept) {
action.accept(p);
}
if ((flags & EachFunc.Break) == EachFunc.Break) {
breaker.set(true);
}
}) && !breaker.get();
}
}, isParallel));
}
@FunctionalInterface
private interface EachFunc {
int None = 0;
int Accept = 1;
int Break = 1 << 1;
int All = Accept | Break;
int each(T t, int index);
}
//endregion
public NQuery each(IndexPredicate func) {
Iterator tor = this.iterator();
int i = 0;
while (tor.hasNext()) {
if (!func.test(tor.next(), i++)) {
break;
}
}
return this;
}
public NQuery select(Function selector) {
return me(stream().map(selector));
}
public NQuery select(IndexSelector selector) {
List result = newList();
AtomicInteger counter = new AtomicInteger();
stream().forEach(t -> result.add(selector.apply(t, counter.getAndIncrement())));
return me(result);
}
public NQuery selectMany(Function> selector) {
return me(stream().flatMap(p -> newStream(selector.apply(p))));
}
public NQuery selectMany(IndexSelector> selector) {
List result = newList();
AtomicInteger counter = new AtomicInteger();
stream().forEach(t -> newStream(selector.apply(t, counter.getAndIncrement())).forEach(result::add));
return me(result);
}
public NQuery where(Predicate predicate) {
return me(stream().filter(predicate));
}
public NQuery where(IndexPredicate predicate) {
List result = newList();
AtomicInteger counter = new AtomicInteger();
stream().forEach(t -> {
if (!predicate.test(t, counter.getAndIncrement())) {
return;
}
result.add(t);
});
return me(result);
}
public NQuery join(Collection inner, BiPredicate keySelector,
BiFunction resultSelector) {
return me(stream().flatMap(
p -> newStream(inner).filter(p2 -> keySelector.test(p, p2)).map(p3 -> resultSelector.apply(p, p3))));
}
public NQuery join(Function innerSelector, BiPredicate keySelector,
BiFunction resultSelector) {
List inner = newList();
stream().forEach(t -> inner.add(innerSelector.apply(t)));
return join(inner, keySelector, resultSelector);
}
public NQuery joinMany(Function> innerSelector, BiPredicate keySelector,
BiFunction resultSelector) {
List inner = newList();
stream().forEach(t -> newStream(innerSelector.apply(t)).forEach(inner::add));
return join(inner, keySelector, resultSelector);
}
public boolean all(Predicate predicate) {
return stream().allMatch(predicate);
}
public boolean any() {
return stream().findAny().isPresent();
}
public boolean any(Predicate predicate) {
return stream().anyMatch(predicate);
}
public boolean contains(T item) {
return stream().anyMatch(p -> p.equals(item));
}
public NQuery concat(Iterable set) {
return concat(App.asList(set));
}
public NQuery concat(Collection set) {
return me(Stream.concat(stream(), newStream(set)));
}
public NQuery distinct() {
return me(stream().distinct());
}
public NQuery except(Iterable set) {
return except(App.asList(set));
}
public NQuery except(Collection set) {
return me(stream().filter(p -> !newStream(set).anyMatch(p2 -> p2.equals(p))));
}
public NQuery intersect(Iterable set) {
return intersect(App.asList(set));
}
public NQuery intersect(Collection set) {
return me(stream().filter(p -> newStream(set).anyMatch(p2 -> p2.equals(p))));
}
public NQuery union(Iterable set) {
return union(App.asList(set));
}
public NQuery union(Collection set) {
return concat(set);
}
public NQuery orderBy(Function keySelector) {
return me(stream().sorted(getComparator(keySelector)));
}
public static Comparator getComparator(Function keySelector) {
return (p1, p2) -> {
Comparable c1 = as(keySelector.apply(p1), Comparable.class);
Comparable c2 = as(keySelector.apply(p2), Comparable.class);
if (c1 == null || c2 == null) {
return 0;
}
return c1.compareTo(c2);
};
}
public NQuery orderByDescending(Function keySelector) {
return me(stream().sorted(getComparator(keySelector).reversed()));
}
public NQuery orderByMany(Function keySelector) {
return me(stream().sorted(getComparatorMany(keySelector)));
}
public static Comparator getComparatorMany(Function keySelector) {
return (p1, p2) -> {
Object[] k1s = keySelector.apply(p1);
Object[] k2s = keySelector.apply(p2);
for (int i = 0; i < k1s.length; i++) {
Comparable c1 = as(k1s[i], Comparable.class);
Comparable c2 = as(k2s[i], Comparable.class);
if (c1 == null || c2 == null) {
continue;
}
int r = c1.compareTo(c2);
if (r == 0) {
continue;
}
return r;
}
return 0;
};
}
public NQuery orderByDescendingMany(Function keySelector) {
return me(stream().sorted(getComparatorMany(keySelector).reversed()));
}
public NQuery reverse() {
return me(stream().sorted((Comparator) ReverseOrder));
}
public NQuery groupBy(Function keySelector, Function>, TR> resultSelector) {
Map> map = newMap();
stream().forEach(t -> map.computeIfAbsent(keySelector.apply(t), p -> newList()).add(t));
List result = newList();
for (Map.Entry> entry : map.entrySet()) {
result.add(resultSelector.apply(Tuple.of(entry.getKey(), of(entry.getValue()))));
}
return me(result);
}
public NQuery groupByMany(Function keySelector,
Function>, TR> resultSelector) {
Map>> map = newMap();
stream().forEach(t -> {
Object[] ks = keySelector.apply(t);
map.computeIfAbsent(toJsonString(ks), p -> Tuple.of(ks, newList())).right.add(t);
});
List result = newList();
for (Tuple