package com.mogo.utils; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Random; import java.util.Set; public final class Dispatch { private static final Dispatch EMPTY = new Dispatch<>(); private final T value; public Dispatch() { this.value = null; } private Dispatch(T value) { this.value = requireNonNull(value); } private static T requireNonNull(T obj) { if (obj == null) { throw new NullPointerException(); } return obj; } private static Dispatch empty() { Dispatch t = (Dispatch) EMPTY; return t; } public static Dispatch of(R value) { return new Dispatch<>(value); } public static Dispatch ofNullable(T value) { return value == null ? (Dispatch) empty() : of(value); } public static DispatchImpl stream(Collection collection) { return new DispatchImpl<>(new ArrayList<>(collection)); } public static DispatchImpl stream(R... values) { List list = new ArrayList<>(); for (R r : values) { list.add(r); } return new DispatchImpl<>(list); } public static DispatchImpl iterate(T seed, final Function mapper, int maxSize) { List list = new ArrayList<>(); list.add(seed); if (maxSize - 1 > 0) { for (int i = 0, len = maxSize - 1; i < len; i++) { list.add(seed = mapper.apply(seed)); } } return new DispatchImpl<>(list); } public final T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; } public final boolean isPresent() { return value != null; } public final void ifPresent(Consumer consumer) { if (value != null) { consumer.accept(value); } } public final Dispatch filter(Predicate predicate) { requireNonNull(predicate); if (!isPresent()) { return this; } else { return predicate.test(value) ? this : (Dispatch) empty(); } } public final Dispatch map(Function mapper) { requireNonNull(mapper); if (!isPresent()) { return empty(); } else { return Dispatch.ofNullable(mapper.apply(value)); } } public final Dispatch flatMap(Function> mapper) { requireNonNull(mapper); if (!isPresent()) { return empty(); } else { return requireNonNull(mapper.apply(value)); } } public final T orElse(T other) { return value != null ? value : other; } public final T orElseGet(Supplier other) { return value != null ? value : other.get(); } public final T orElseThrow(Supplier exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } } @Override public final boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Dispatch)) { return false; } Dispatch other = (Dispatch) obj; return Objects.equals(value, other.value); } @Override public final int hashCode() { return value != null ? value.hashCode() : 0; } @Override public final String toString() { return value != null ? String.format("Dispatch[%s]", value) : "Dispatch.empty"; } public final static class DispatchImpl { private final List value; private DispatchImpl() { this.value = null; } private DispatchImpl(List value) { this.value = value; } public final boolean isPresent() { return value != null; } public final DispatchImpl filter(Predicate predicate) { requireNonNull(predicate); if (isPresent()) { forEach(e -> { if (!predicate.test(e)) { this.value.remove(e); } }); } return this; } public final DispatchImpl map(Function mapper) { requireNonNull(mapper); List target = new ArrayList<>(); if (isPresent()) { for (E e : value) { target.add(mapper.apply(e)); } } return new DispatchImpl<>(target); } /** * 多个数组数据源转换成一个数组数据源 * * @param mapper * @param * @return */ public final DispatchImpl flatMap(Function> mapper) { requireNonNull(mapper); List dispatchStream = new ArrayList<>(); if (isPresent()) { this.forEach(e -> { dispatchStream.addAll(((DispatchImpl) mapper.apply(e)).value); }); } return new DispatchImpl<>(dispatchStream); } public final DispatchImpl distinct() { List target = new ArrayList<>(); if (isPresent()) { for (E e : value) { if (!target.contains(e)) { target.add(e); } } } return this; } public final DispatchImpl forEach(Consumer action) { requireNonNull(action); if (isPresent()) { for (E e : value) { action.accept(e); } } return this; } public final DispatchImpl forEach(BiConsumer action) { requireNonNull(action); if (isPresent()) { for (int i = 0, len = value.size(); i < len; i++) { action.accept(i, value.get(i)); } } return this; } public final DispatchImpl limit(int maxSize) { if (this.isPresent() && maxSize > 0) { return new DispatchImpl<>(this.value.subList(0, maxSize > this.count() ? this.count() : maxSize)); } return this; } public final DispatchImpl skip(int n) { if (this.isPresent() && n > 0 && n < count()) { return new DispatchImpl<>(this.value.subList(n, this.count())); } return this; } public final DispatchImpl peek(Consumer action) { if (this.isPresent()) { forEach(action); } forEach(action); return this; } public final DispatchImpl sorted() { return sorted(Object::hashCode); } public final > DispatchImpl sorted(Function function) { requireNonNull(function); return sorted((Comparator & Serializable) (c1, c2) -> function.apply(c1).compareTo(function.apply(c2))); } public final DispatchImpl sorted(Comparator comparator) { requireNonNull(comparator); if (isPresent()) { Collections.sort(value, comparator); } return this; } public final int count() { if (isPresent()) { return value.size(); } return 0; } public final Dispatch findFirst() { if (isPresent() && value.size() > 0) { return Dispatch.ofNullable(value.get(0)); } return Dispatch.empty(); } public final Dispatch findAny() { if (isPresent() && value.size() > 0) { return Dispatch.ofNullable(value.get(new Random().nextInt(value.size()))); } return Dispatch.empty(); } public final Dispatch findAny(Predicate predicate) { if (isPresent() && value.size() > 0) { for (E e : value) { if (predicate.test(e)) { return Dispatch.ofNullable(e); } } } return Dispatch.empty(); } public final E[] toArray() { if (isPresent()) { return (E[]) this.value.toArray(); } return null; } /** * 输出需要的数据类型 * * @param supplier * @param accumulator * @return */ public final R toCollect(Supplier supplier, BiConsumer accumulator) { requireNonNull(supplier); requireNonNull(accumulator); R r = supplier.get(); forEach(t -> { accumulator.accept(r, t); }); return r; } public final R toCollection(Supplier supplier) { return toCollect(supplier, Collection::add); } public final List toList() { return toCollection((Supplier>) ArrayList::new); } public final Set toSet() { return toCollection((Supplier>) HashSet::new); } public final Map toMap(Function keyMapper, Function valueMapper, BiFunction mergeFunction, Supplier> mapSupplier) { BiConsumer, E> accumulator = (map, element) -> { K key = keyMapper.apply(element); U value = valueMapper.apply(element); U oldValue = map.get(key); U newValue = (oldValue == null) ? value : mergeFunction.apply(oldValue, value); if (newValue == null) { map.remove(key); } else { map.put(key, newValue); } }; return this.toCollect(HashMap::new, accumulator); } public final Map toMap(Function keyMapper, Function valueMapper, BiFunction mergeFunction) { return this.toMap(keyMapper, valueMapper, (u, v) -> mergeFunction.apply(u, v), (Supplier>) HashMap::new); } public final Map toMap(Function keyMapper, Function valueMapper) { return this.toMap(keyMapper, valueMapper, (u, v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }); } public final Map> toGroupingBy(Function classifier) { return toGroupingBy(classifier, (Supplier>>) HashMap::new); } public final Map> toGroupingBy(Function classifier, Supplier>> mapFactory) { BiConsumer>, E> accumulator = (map, element) -> { K key = classifier.apply(element); if (map.containsKey(key)) { List temp = map.get(key); temp.add(element); } else { List list = new ArrayList<>(); list.add(element); map.put(key, list); } }; return toCollect(mapFactory, accumulator); } public final E toJoin(BiFunction biFunction) { requireNonNull(biFunction); BiFunction temp = (t, u) -> { if (t == null) { return u; } else { return biFunction.apply(t, u); } }; E apply = null; if (isPresent()) { for (int i = 0, len = value.size() - 1; i <= len; i++) { apply = temp.apply(apply, value.get(i)); } } return apply; } @Override public final String toString() { return isPresent() ? value.toString() : super.toString(); } } public interface Supplier { /** * Gets a result. * * @return a result */ T get(); } public interface BiConsumer { /** * Performs this operation on the given arguments. * * @param t the first input argument * @param u the second input argument */ void accept(T t, U u); } public interface BiFunction { /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result */ R apply(T t, U u); } public interface Consumer { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); } public interface Predicate { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); } public interface Function { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); } }