package org.springside.modules.utils.collection; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; import org.springside.modules.utils.collection.type.SortedArrayList; import com.google.common.collect.Lists; /** * 关于List的工具集合. * * 1. 常用函数(如是否为空,sort/binarySearch/shuffle/reverse(via JDK Collection) * * 2. 各种构造函数(from guava and JDK Collection) * * 3. 各种扩展List类型的创建函数 * * 5. 集合运算:交集,并集, 差集, 补集,from Commons Collection,但对其不合理的地方做了修正 * * @author calvin */ @SuppressWarnings("unchecked") public class ListUtil { /** * 判断是否为空. */ public static boolean isEmpty(List<?> list) { return (list == null) || list.isEmpty(); } /** * 判断是否不为空. */ public static boolean isNotEmpty(List<?> list) { return (list != null) && !(list.isEmpty()); } /** * 获取第一个元素, 如果List为空返回 null. */ public static <T> T getFirst(List<T> list) { if (isEmpty(list)) { return null; } return list.get(0); } /** * 获取最后一个元素,如果List为空返回null. */ public static <T> T getLast(List<T> list) { if (isEmpty(list)) { return null; } return list.get(list.size() - 1); } ///////////////// from Guava的构造函数/////////////////// /** * 根据等号左边的类型,构造类型正确的ArrayList. * * @see com.google.common.collect.Lists#newArrayList() */ public static <T> ArrayList<T> newArrayList() { return new ArrayList<T>(); } /** * 根据等号左边的类型,构造类型正确的ArrayList, 并初始化元素. * * @see com.google.common.collect.Lists#newArrayList(Object...) */ public static <T> ArrayList<T> newArrayList(T... elements) { return Lists.newArrayList(elements); } /** * 根据等号左边的类型,构造类型正确的ArrayList, 并初始化元素. * * @see com.google.common.collect.Lists#newArrayList(Iterable) */ public static <T> ArrayList<T> newArrayList(Iterable<T> elements) { return Lists.newArrayList(elements); } /** * 根据等号左边的类型,构造类型正确的ArrayList, 并初始化数组大小. * * @see com.google.common.collect.Lists#newArrayListWithCapacity(int) */ public static <T> ArrayList<T> newArrayListWithCapacity(int initSize) { return new ArrayList<T>(initSize); } /** * 根据等号左边的类型,构造类型正确的LinkedList. * * @see com.google.common.collect.Lists#newLinkedList() */ public static <T> LinkedList<T> newLinkedList() { return new LinkedList<T>(); } /** * 根据等号左边的类型,构造类型正确的LinkedList. * * @see com.google.common.collect.Lists#newLinkedList() */ public static <T> LinkedList<T> newLinkedList(Iterable<? extends T> elements) { return Lists.newLinkedList(elements); } /** * 根据等号左边的类型,构造类型正确的CopyOnWriteArrayList. * * @see com.google.common.collect.Lists#newCopyOnWriteArrayList() */ public static <T> CopyOnWriteArrayList<T> newCopyOnWriteArrayList() { return new CopyOnWriteArrayList<T>(); } /** * 根据等号左边的类型,构造类型转换的CopyOnWriteArrayList, 并初始化元素. */ public static <T> CopyOnWriteArrayList<T> newCopyOnWriteArrayList(T... elements) { return new CopyOnWriteArrayList<T>(elements); } ////////////// 特别类型的List////////////// /** * 构造排序的ArrayList. * * from Jodd的新类型,插入时排序,但指定插入index的方法如add(index,element)不支持 */ @SuppressWarnings("rawtypes") public static <T extends Comparable> SortedArrayList<T> createSortedArrayList() { return new SortedArrayList<T>(); } /** * 构造排序的ArrayList. * * from Jodd的新类型,插入时排序,但指定插入index的方法如add(index,element)不支持 */ public static <T> SortedArrayList<T> createSortedArrayList(Comparator<? super T> c) { return new SortedArrayList<T>(c); } ///////////////// from JDK Collections的常用构造函数 /////////////////// /** * 返回一个空的结构特殊的List,节约空间. * * 注意返回的List不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#emptyList() */ public static final <T> List<T> emptyList() { return (List<T>) Collections.EMPTY_LIST; } /** * 如果list为null,转化为一个安全的空List. * * 注意返回的List不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#emptyList() */ public static <T> List<T> emptyListIfNull(final List<T> list) { return list == null ? (List<T>) Collections.EMPTY_LIST : list; } /** * 返回只含一个元素但结构特殊的List,节约空间. * * 注意返回的List不可写, 写入会抛出UnsupportedOperationException. * * @see java.util.Collections#singletonList(Object) */ public static <T> List<T> singletonList(T o) { return Collections.singletonList(o); } /** * 返回包装后不可修改的List. * * 如果尝试写入会抛出UnsupportedOperationException. * * @see java.util.Collections#unmodifiableList(List) */ public static <T> List<T> unmodifiableList(List<? extends T> list) { return Collections.unmodifiableList(list); } /** * 返回包装后同步的List,所有方法都会被synchronized原语同步. * * 用于CopyOnWriteArrayList与 ArrayDequeue均不符合的场景 */ public static <T> List<T> synchronizedList(List<T> list) { return Collections.synchronizedList(list); } ///////////////// from JDK Collections的常用函数 /////////////////// /** * 升序排序, 采用JDK认为最优的排序算法, 使用元素自身的compareTo()方法 * * @see java.util.Collections#sort(List) */ public static <T extends Comparable<? super T>> void sort(List<T> list) { Collections.sort(list); } /** * 倒序排序, 采用JDK认为最优的排序算法,使用元素自身的compareTo()方法 * * @see java.util.Collections#sort(List) */ public static <T extends Comparable<? super T>> void sortReverse(List<T> list) { Collections.sort(list, Collections.reverseOrder()); } /** * 升序排序, 采用JDK认为最优的排序算法, 使用Comparetor. * * @see java.util.Collections#sort(List, Comparator) */ public static <T> void sort(List<T> list, Comparator<? super T> c) { Collections.sort(list, c); } /** * 倒序排序, 采用JDK认为最优的排序算法, 使用Comparetor * * @see java.util.Collections#sort(List, Comparator) */ public static <T> void sortReverse(List<T> list, Comparator<? super T> c) { Collections.sort(list, Collections.reverseOrder(c)); } /** * 二分法快速查找对象, 使用Comparable对象自身的比较. * * list必须已按升序排序. * * 如果不存在,返回一个负数,代表如果要插入这个对象,应该插入的位置 * * @see java.util.Collections#binarySearch(List, Object) */ public static <T> int binarySearch(List<? extends Comparable<? super T>> sortedList, T key) { return Collections.binarySearch(sortedList, key); } /** * 二分法快速查找对象,使用Comparator. * * list必须已按升序排序. * * 如果不存在,返回一个负数,代表如果要插入这个对象,应该插入的位置 * * @see java.util.Collections#binarySearch(List, Object, Comparator) */ public static <T> int binarySearch(List<? extends T> sortedList, T key, Comparator<? super T> c) { return Collections.binarySearch(sortedList, key, c); } /** * 随机乱序,使用默认的Random. * * @see java.util.Collections#shuffle(List) */ public static void shuffle(List<?> list) { Collections.shuffle(list); } /** * 返回一个倒转顺序访问的List,仅仅是一个倒序的View,不会实际多生成一个List * * @see com.google.common.collect.Lists#reverse(List) */ public static <T> List<T> reverse(final List<T> list) { return Lists.reverse(list); } /** * 随机乱序,使用传入的Random. * * @see java.util.Collections#shuffle(List, Random) */ public static void shuffle(List<?> list, Random rnd) { Collections.shuffle(list, rnd); } ///////////////// 集合运算 /////////////////// /** * list1,list2的并集(在list1或list2中的对象),产生新List * * 对比Apache Common Collection4 ListUtils, 优化了初始大小 */ public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) { final List<E> result = new ArrayList<E>(list1.size() + list2.size()); result.addAll(list1); result.addAll(list2); return result; } /** * list1, list2的交集(同时在list1和list2的对象),产生新List * * from Apache Common Collection4 ListUtils,但其做了不合理的去重,因此重新改为性能较低但不去重的版本 * * 与List.retainAll()相比,考虑了的List中相同元素出现的次数, 如"a"在list1出现两次,而在list2中只出现一次,则交集里会保留一个"a". */ public static <T> List<T> intersection(final List<? extends T> list1, final List<? extends T> list2) { List<? extends T> smaller = list1; List<? extends T> larger = list2; if (list1.size() > list2.size()) { smaller = list2; larger = list1; } // 克隆一个可修改的副本 List<T> newSmaller = new ArrayList<T>(smaller); List<T> result = new ArrayList<T>(smaller.size()); for (final T e : larger) { if (newSmaller.contains(e)) { result.add(e); newSmaller.remove(e); } } return result; } /** * list1, list2的差集(在list1,不在list2中的对象),产生新List. * * 与List.removeAll()相比,会计算元素出现的次数,如"a"在list1出现两次,而在list2中只出现一次,则差集里会保留一个"a". */ public static <T> List<T> difference(final List<? extends T> list1, final List<? extends T> list2) { final List<T> result = new ArrayList<T>(list1); final Iterator<? extends T> iterator = list2.iterator(); while (iterator.hasNext()) { result.remove(iterator.next()); } return result; } /** * list1, list2的补集(在list1或list2中,但不在交集中的对象,又叫反交集)产生新List. * * from Apache Common Collection4 ListUtils,但其并集-交集时,没有对交集*2,所以做了修改 */ public static <T> List<T> disjoint(final List<? extends T> list1, final List<? extends T> list2) { List<T> intersection = intersection(list1, list2); List<T> towIntersection = union(intersection, intersection); return difference(union(list1, list2), towIntersection); } }