org.rx.core.Linq 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.core;
import io.netty.util.internal.ThreadLocalRandom;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.rx.annotation.ErrorCode;
import org.rx.bean.$;
import org.rx.bean.Decimal;
import org.rx.bean.Tuple;
import org.rx.exception.ApplicationException;
import org.rx.util.function.*;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.ToDoubleFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static org.rx.bean.$.$;
import static org.rx.core.Constants.NON_RAW_TYPES;
import static org.rx.core.Constants.NON_UNCHECKED;
import static org.rx.core.Extends.*;
/**
* https://msdn.microsoft.com/en-us/library/bb738550(v=vs.110).aspx
*/
@Slf4j
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class Linq implements Iterable, Serializable {
private static final long serialVersionUID = -7167070585936243198L;
static final Linq EMPTY = new Linq<>(Collections.emptyList(), false);
//region staticMembers
public static boolean tryAsIterableType(Class> type) {
return Iterable.class.isAssignableFrom(type)
|| type.isArray()
|| Iterator.class.isAssignableFrom(type);
}
@SuppressWarnings(NON_UNCHECKED)
@ErrorCode
public static Iterable asIterable(@NonNull Object collection, boolean throwOnFail) {
if (collection instanceof Iterable) {
return (Iterable) collection;
}
Class> type = collection.getClass();
if (type.isArray()) {
int length = Array.getLength(collection);
List list = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
list.add((T) Array.get(collection, i));
}
return list;
}
if (collection instanceof Iterator) {
return IteratorUtils.asIterable((Iterator) collection);
}
if (throwOnFail) {
throw new ApplicationException(values(type.getSimpleName()));
}
return null;
}
public static Linq empty() {
return (Linq) EMPTY;
}
public static Linq fromIterable(Object iterable) {
return from(asIterable(iterable, true));
}
public static Linq from(T one) {
if (one == null) {
return EMPTY;
}
return from(Arrays.toList(one));
}
@SafeVarargs
public static Linq from(T... array) {
return from(Arrays.toList(array));
}
public static Linq from(Stream stream) {
if (stream == null) {
return EMPTY;
}
return from(stream::iterator, stream.isParallel());
}
public static Linq from(Iterable iterable) {
return from(iterable, false);
}
public static Linq from(Iterable iterable, boolean isParallel) {
return iterable == null ? EMPTY : new Linq<>(iterable, isParallel);
}
//endregion
//region Member
private final Iterable data;
private final boolean parallel;
public Stream stream() {
return StreamSupport.stream(data.spliterator(), parallel);
}
private List newList() {
Collection ts = asCollection();
int count = ts != null ? ts.size() : 0;
return parallel ? newConcurrentList(count, false) : new ArrayList<>(count);
}
private Set newSet() {
Collection ts = asCollection();
int count = ts != null ? ts.size() : 16;
return parallel ? Collections.synchronizedSet(new LinkedHashSet<>(count)) : new LinkedHashSet<>(count);
}
private Map newMap() {
Collection ts = asCollection();
int count = ts != null ? ts.size() : 16;
return parallel ? Collections.synchronizedMap(new LinkedHashMap<>(count)) : new LinkedHashMap<>(count);
}
private Collection asCollection() {
return data instanceof Collection ? (Collection) data : null;
}
private Stream newStream(Iterable iterable) {
return StreamSupport.stream(iterable.spliterator(), parallel);
}
private Linq me(Iterable set) {
return from(set, parallel);
}
private Linq me(Stream stream) {
return me(stream.collect(Collectors.toList()));
}
@SneakyThrows
private Linq me(EachFunc func, String prevMethod) {
if (parallel) {
log.warn("Not support parallel {}", prevMethod);
}
Spliterator spliterator = data.spliterator();
Stream r = StreamSupport.stream(new Spliterators.AbstractSpliterator(spliterator.estimateSize(), spliterator.characteristics()) {
final AtomicBoolean breaker = new AtomicBoolean();
final AtomicInteger counter = new AtomicInteger();
@Override
public boolean tryAdvance(Consumer super T> 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();
}
}, parallel);
return me(r);
}
@FunctionalInterface
interface EachFunc {
int NONE = 0;
int ACCEPT = 1;
int BREAK = 1 << 1;
int each(T item, int index);
}
//endregion
@Override
public Iterator iterator() {
return data.iterator();
}
@Override
public void forEach(Consumer super T> action) {
stream().forEach(action);
}
public void forEachOrdered(Consumer super T> action) {
stream().forEachOrdered(action);
}
public Linq select(BiFunc selector) {
return me(stream().map(selector));
}
public Linq select(BiFuncWithIndex selector) {
AtomicInteger counter = new AtomicInteger();
return me(stream().map(p -> selector.apply(p, counter.getAndIncrement())));
}
public Linq selectMany(BiFunc> selector) {
return me(stream().flatMap(p -> newStream(selector.apply(p))));
}
public Linq selectMany(BiFuncWithIndex> selector) {
AtomicInteger counter = new AtomicInteger();
return me(stream().flatMap(p -> newStream(selector.apply(p, counter.getAndIncrement()))));
}
public Linq where(PredicateFunc predicate) {
return me(stream().filter(predicate));
}
public Linq where(PredicateFuncWithIndex predicate) {
AtomicInteger counter = new AtomicInteger();
return me(stream().filter(p -> predicate.test(p, counter.getAndIncrement())));
}
public Linq join(Iterable inner, BiPredicate keySelector, TripleFunc resultSelector) {
return me(stream().flatMap(p -> newStream(inner).filter(p2 -> keySelector.test(p, p2)).map(p3 -> resultSelector.apply(p, p3))));
}
public Linq join(BiFunc innerSelector, BiPredicate keySelector, TripleFunc resultSelector) {
return join(stream().map(innerSelector).collect(Collectors.toList()), keySelector, resultSelector);
}
public Linq joinMany(BiFunc> innerSelector, BiPredicate keySelector, TripleFunc resultSelector) {
return join(stream().flatMap(p -> newStream(innerSelector.apply(p))).collect(Collectors.toList()), keySelector, resultSelector);
}
public Linq leftJoin(Iterable inner, BiPredicate keySelector, TripleFunc resultSelector) {
return me(stream().flatMap(p -> {
if (!newStream(inner).anyMatch(p2 -> keySelector.test(p, p2))) {
return Stream.of(resultSelector.apply(p, null));
}
return newStream(inner).filter(p2 -> keySelector.test(p, p2)).map(p3 -> resultSelector.apply(p, p3));
}));
}
public Linq leftJoin(BiFunc innerSelector, BiPredicate keySelector, TripleFunc resultSelector) {
return leftJoin(stream().map(innerSelector).collect(Collectors.toList()), keySelector, resultSelector);
}
public Linq leftJoinMany(BiFunc> innerSelector, BiPredicate keySelector, TripleFunc resultSelector) {
return leftJoin(stream().flatMap(p -> newStream(innerSelector.apply(p))).collect(Collectors.toList()), keySelector, resultSelector);
}
public boolean all(PredicateFunc predicate) {
return stream().allMatch(predicate);
}
public boolean any() {
return stream().findAny().isPresent();
}
public boolean any(PredicateFunc predicate) {
return stream().anyMatch(predicate);
}
public boolean contains(T item) {
return stream().anyMatch(p -> p.equals(item));
}
public Linq concat(Iterable set) {
return me(Stream.concat(stream(), newStream(set)));
}
public Linq distinct() {
return me(stream().distinct());
}
public Linq except(Iterable set) {
return me(stream().filter(p -> !newStream(set).anyMatch(p2 -> p2.equals(p))));
}
public Linq intersection(Iterable set) {
return me(stream().filter(p -> newStream(set).anyMatch(p2 -> p2.equals(p))));
}
public Linq difference(Iterable set) {
return Linq.from(CollectionUtils.disjunction(this, set));
}
public Linq union(Iterable set) {
return Linq.from(CollectionUtils.union(this, set));
}
//ListUtils.partition()
public Linq> partition(int size) {
List> n = newList();
List a = toList();
int f = 0, t = 0;
while (f < a.size()) {
t = Math.min(t + size, a.size());
n.add(a.subList(f, t));
f = t;
}
return me(n);
}
public Linq orderByRand() {
return me(stream().sorted(getComparator(p -> ThreadLocalRandom.current().nextInt(0, 100), false)));
}
public Linq orderBy(BiFunc keySelector) {
// return me(stream().sorted(Comparator.nullsLast(Comparator.comparing((Function) keySelector))));
return me(stream().sorted(getComparator(keySelector, false)));
}
@SuppressWarnings(NON_RAW_TYPES)
public static Comparator getComparator(BiFunc keySelector, boolean descending) {
return (p1, p2) -> {
Comparable a = as(keySelector.apply(p1), Comparable.class);
Comparable b = as(keySelector.apply(p2), Comparable.class);
boolean nullFirst = false;
if (a == null) {
return b == null ? 0 : (nullFirst ? -1 : 1);
}
if (b == null) {
return nullFirst ? 1 : -1;
}
return descending ? b.compareTo(a) : a.compareTo(b);
};
}
public Linq orderByDescending(BiFunc keySelector) {
return me(stream().sorted(getComparator(keySelector, true)));
}
public Linq orderByMany(BiFunc> keySelector) {
return me(stream().sorted(getComparatorMany(keySelector, false)));
}
@SuppressWarnings(NON_RAW_TYPES)
public static Comparator getComparatorMany(BiFunc> keySelector, boolean descending) {
return (p1, p2) -> {
List