Java 1.7 NQuery

package org.rx.common;

import java.lang.reflect.Array;
import java.util.*;

/**
 * Created by wangxiaoming on 2016/3/3.
 * https://msdn.microsoft.com/en-us/library/bb738550(v=vs.110).aspx
 */
public class NQuery<T> implements Iterable<T> {
    //region Properties
    private List<T> current;

    public NQuery(T[] set) {
        if (set == null) {
            throw new IllegalArgumentException("set == null");
        }
        current = Arrays.asList(set);
    }

    public NQuery(Iterable<T> set) {
        if (set == null) {
            throw new IllegalArgumentException("set == null");
        }
        current = toList(set);
    }

    private NQuery(List<T> list) {
        current = list;
    }
    //endregion

    //region Methods
    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            private int offset;

            @Override
            public boolean hasNext() {
                return current.size() > offset;
            }

            @Override
            public T next() {
                return current.get(offset++);
            }

            @Override
            public void remove() {

            }
        };
    }

    private List<T> toList(Iterable<T> set) {
        List<T> list = new ArrayList<>();
        for (T t : set) {
            list.add(t);
        }
        return list;
    }
    //endregion

    //region PRMethods
    public NQuery<T> where(Func<T, Boolean> selector) {
        List<T> result = new ArrayList<>();
        for (T t : current) {
            if (selector.invoke(t)) {
                result.add(t);
            }
        }
        return new NQuery<>(result);
    }

    public <TR> NQuery<TR> select(Func<T, TR> selector) {
        List<TR> result = new ArrayList<>();
        for (T t : current) {
            result.add(selector.invoke(t));
        }
        return new NQuery<>(result);
    }

    public <TR> NQuery<TR> selectMany(Func<T, Iterable<TR>> selector) {
        List<TR> result = new ArrayList<>();
        for (T t : current) {
            for (TR tr : selector.invoke(t)) {
                result.add(tr);
            }
        }
        return new NQuery<>(result);
    }
    //endregion

    //region JoinMethods
    public <TI, TR> NQuery<TR> join(Iterable<TI> inner, BiFunc<T, TI, Boolean> keySelector,
                                    BiFunc<T, TI, TR> resultSelector) {
        List<TR> result = new ArrayList<>();
        for (T t : current) {
            for (TI ti : inner) {
                if (!keySelector.invoke(t, ti)) {
                    continue;
                }
                result.add(resultSelector.invoke(t, ti));
            }
        }
        return new NQuery<>(result);
    }
    //endregion

    //region SetMethods
    public boolean any() {
        return current.size() > 0;
    }

    public boolean any(Func<T, Boolean> selector) {
        return this.where(selector).any();
    }

    public NQuery<T> except(Iterable<T> set) {
        List<T> result = toList();
        for (T t : set) {
            result.remove(t);
        }
        return new NQuery<>(result);
    }

    public NQuery<T> intersect(Iterable<T> set) {
        List<T> result = toList();
        result.retainAll(toList(set));
        return new NQuery<>(result);
    }

    public NQuery<T> union(Iterable<T> set) {
        HashSet<T> result = new HashSet<>();
        result.addAll(current);
        result.addAll(toList(set));
        return new NQuery<>(result);
    }
    //endregion

    //region OrderingMethods
    public <TK> NQuery<T> orderBy(final Func<T, TK> keySelector) {
        List<T> result = toList();
        Collections.sort(result, new Comparator<T>() {
            @Override
            public int compare(T o1, T o2) {
                TK tk = keySelector.invoke(o1);
                if (!Comparable.class.isAssignableFrom(tk.getClass())) {
                    return 0;
                }
                Comparable c = (Comparable) tk;
                return c.compareTo(keySelector.invoke(o2));
            }
        });
        return new NQuery<>(result);
    }

    public <TK> NQuery<T> orderByDescending(final Func<T, TK> keySelector) {
        List<T> result = toList();
        Collections.sort(result, new Comparator<T>() {
            @Override
            public int compare(T o1, T o2) {
                TK tk = keySelector.invoke(o1);
                if (!Comparable.class.isAssignableFrom(tk.getClass())) {
                    return 0;
                }
                Comparable c = (Comparable) tk;
                int val = c.compareTo(keySelector.invoke(o2));
                if (val == 1) {
                    return -1;
                } else if (val == -1) {
                    return 1;
                }
                return val;
            }
        });
        return new NQuery<>(result);
    }
    //endregion

    //region GroupingMethods
    public <TK, TR> NQuery<TR> groupBy(Func<T, TK> keySelector, Func<Tuple<TK, NQuery<T>>, TR> resultSelector) {
        Map<TK, List<T>> map = new HashMap<>();
        for (T t : current) {
            TK key = keySelector.invoke(t);
            if (map.get(key) == null) {
                map.put(key, new ArrayList<T>());
            }
            map.get(key).add(t);
        }
        List<TR> result = new ArrayList<>();
        for (TK tk : map.keySet()) {
            result.add(resultSelector.invoke(Tuple.of(tk, new NQuery<>(map.get(tk)))));
        }
        return new NQuery<>(result);
    }
    //endregion

    //region AggregateMethods
    public int count() {
        return current.size();
    }
    //endregion

    //region PagingMethods
    public T first() {
        return current.get(0);
    }

    public T firstOrDefault() {
        if (current.size() == 0) {
            return null;
        }
        return first();
    }

    public T last() {
        return current.get(current.size() - 1);
    }

    public T lastOrDefault() {
        if (current.size() == 0) {
            return null;
        }
        return last();
    }
    //endregion

    //region ToMethods
    public T[] toArray(Class<T> type) {
        T[] set = (T[]) Array.newInstance(type, current.size());
        current.toArray(set);
        return set;
    }

    public List<T> toList() {
        return new ArrayList<>(current);
    }

    public Set<T> toSet() {
        return new HashSet<>(current);
    }

    public <TK> Map<TK, T> toMap(Func<T, TK> keySelector) {
        HashMap<TK, T> map = new HashMap<>();
        for (T t : current) {
            map.put(keySelector.invoke(t), t);
        }
        return map;
    }

    public <TK, TV> Map<TK, TV> toMap(Func<T, TK> keySelector, Func<T, TV> valueSelector) {
        HashMap<TK, TV> map = new HashMap<>();
        for (T t : current) {
            map.put(keySelector.invoke(t), valueSelector.invoke(t));
        }
        return map;
    }
    //endregion
}
package org.rx.common;

public interface BiFunc<T1, T2, T3> {
    T3 invoke(T1 arg1, T2 arg2);
}
原文地址:https://www.cnblogs.com/Googler/p/7485723.html