Java8集合框架——集合工具类Collections内部方法浅析

Posted wpbxin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8集合框架——集合工具类Collections内部方法浅析相关的知识,希望对你有一定的参考价值。

本文的目录结构:

零:Collections 的官方注释

  英文注解比较简短,直接贴了出来。大致说几点:

  • 提供专门操作或者返回 collections 的静态方法,包含了多种算法;
  • 参数为 null 时抛出 NullPointerException;
  • 文档注释应当成是具体实现的注意事项,而不是规范;实现者应该可以自由地替换其他算法,只要遵守规范本身。
  • 对于会修改集合的“破坏性”算法,如果集合不支持可变操作(如 set ),将抛出异常 UnsupportedOperationException 。如果调用对集合没有影响,这些算法可能会抛出此异常,但不是必需的。例如,在已经排序的不可修改列表上调用排序方法可能会引发UnsupportedOperationException,也可能不会引发UnsupportedOperationException。

This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

The methods of this class all throw a NullPointerException if the collections or class objects provided to them are null.

The documentation for the polymorphic algorithms contained in this class generally includes a brief description of the implementation. Such descriptions should be regarded as implementation notes, rather than parts of the specification. Implementors should feel free to substitute other algorithms, so long as the specification itself is adhered to. (For example, the algorithm used by sort does not have to be a mergesort, but it does have to be stable.)

The "destructive" algorithms contained in this class, that is, the algorithms that modify the collection on which they operate, are specified to throw UnsupportedOperationException if the collection does not support the appropriate mutation primitive(s), such as the set method. These algorithms may, but are not required to, throw this exception if an invocation would have no effect on the collection. For example, invoking the sort method on an unmodifiable list that is already sorted may or may not throw UnsupportedOperationException.

  另外,根据其他注释,可以看出 Collections 大致分了 Algorithms(算法类操作)Unmodifiable Wrappers(不可变包装类)Synch Wrappers(同步安全包装类)Dynamically typesafe collection wrappers(动态类型安全集合包装类)Empty collections(空集合)Singleton collections(单例集合)Miscellaneous(杂项/其他) 总共 7 大类方法。下面根据这 7 大类进行介绍。

  1. Algorithms(算法类操作):一些针对集合的常用算法操作,比如排序、二分查找、最小/最大元素等等。
  2. Unmodifiable Wrappers(不可变包装类):返回集合的只读视图,任何修改操作都将抛出 UnsupportedOperationException。
  3. Synch Wrappers(同步安全包装类):返回集合的线程安全包装类。
  4. Dynamically typesafe collection wrappers(动态类型安全集合包装类):返回集合的类型安全包装类,确保元素类型的唯一性。
  5. Empty collections(空集合):没有元素的空集合,size() = 0
  6. Singleton collections(单例集合):只有1个元素的不可变集合
  7. Miscellaneous(杂项/其他)

一、Algorithms(算法类操作)

01、排序 sort

  其实这2个都只是直接调用了 List 本身就有的 sort 方法进行排序,可以直接替换的。

// 升序排序,稳定排序,内部使用List.sort
public static <T extends Comparable<? super T>> void sort(List<T> list) {...}
// 根据指定的 Comparator 进行排序,内部使用 List.sort(Comparator<? super T> c)
public static <T> void sort(List<T> list, Comparator<? super T> c)

  

02、二分查找 binarySearch

  在已排序升序的 List 中进行二分查找

// 在已经升序排序的 List 中进行二分查找,内部会分为 
// 1、Collections.indexedBinarySearch:RandomAccess 实现类或者 List 的大小小于5000(BINARYSEARCH_THRESHOLD),例如 ArrayList
// 2、Collections.iteratorBinarySearch:其他类型的 List,例如 LinkedList
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {...}
// 与上面方法类似,只是这里的比较大小使用的是入参 Comparator
public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {...}

 

03、列表反转 reverse

  对列表进行反转。

public static void reverse(List<?> list) {...}

 

04、元素重排列 shuffle

  对列表进行重新排列,洗牌。按顺序对列表进行遍历,然后根据产生的随机数对元素进行交换。

// 内部产生随机数再调用 shuffle(List<?> list, Random rnd)
public static void shuffle(List<?> list) {...}
// 通过指定的随机数对 List 元素的进行随机交换,对于非 RandomAccess 实现类,需要先转换再 shuffle 再转回去
public static void shuffle(List<?> list, Random rnd) {...}

  

05、元素交换 swap

  交换指定索引的列表元素。

public static void swap(List<?> list, int i, int j) {
    // instead of using a raw type here, it‘s possible to capture
    // the wildcard but it will require a call to a supplementary
    // private method
    final List l = list;
    l.set(i, l.set(j, l.get(i)));
}

 

06、列表填充 fill

  用指定的元素 obj 填充所有列表元素。

// 用指定的元素 obj 填充所有列表元素
public static <T> void fill(List<? super T> list, T obj) {...}

 

07、元素复制 copy

  将源列表 src 中的元素复制到目的地列表 dest 中去,目的地列表容量需要足够容纳 src,dest.size() >= src.size()

// 将源列表 src 中的元素复制到目的地列表 dest 中去,目的地列表容量需要足够容纳 src
public static <T> void copy(List<? super T> dest, List<? extends T> src) {...}

  

08、最小/最大元素查找 min/max

  列表最小/最大元素查找。

// 最小元素查找,比较大小用的是元素本身的 compareTo 方法
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {...}
// 最小元素查找,比较大小用的是元素 Comparator.compare(? super T o1, ? super T o2)
public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {...}

// 最大元素查找,比较大小用的是元素本身的 compareTo 方法
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {...}
// 最大元素查找,比较大小用的是元素 Comparator.compare(? super T o1, ? super T o2)
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {...}

  

09、数组旋转 rotate

  根据指定的间距旋转数组,其实就是右移 distance 个位置,如果 distance 为负数,则是右移 size + distance 个位置。

/**
* 旋转之后,现在的 list[i] 是原来的 list[(i-distance)%size]。列表[t, a, n, k, s]执行Collections.rotate(list, 1)
* 或者Collections.rotate(list, -4)结果是一样的,都是[s, t, a, n, k]。
* 该方法对于移动子列表中的一个或者而多个元素也是有效的。下面这个调用就是将 index[j] 移动到 index[k],中间的左移1个位置
* Collections.rotate(list.subList(j, k+1), -1);
* 例如列表[a, b, c, d, e],将 index[1] 的 b 往右挪 2 格,也即是 d 的位置 index[3],则调用是 Collections.rotate(l.subList(1, 4), -1); 结果[a, c, d, b, e]
* 如果要旋转多个元素,则增大旋转间距的绝对值即可。还是上面的例子,调用 Collections.rotate(l.subList(1, 4), -2) 之后就是[a, d, b, c, e]
* 如果按照相反的位置挪动的话,使用正的 distance
* 
*/
public static void rotate(List<?> list, int distance) {
    if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
        rotate1(list, distance);
    else
        rotate2(list, distance);
}
// 下面这2个算法可以具体参考 Jon Bentley的《Programming Pearls》即《编程珠玑》的 2.3 节
// 这实现方法挺有意思的,就是间隔 distance 个进行交换,多来几圈就全部完成了
private static <T> void rotate1(List<T> list, int distance) {
    int size = list.size();
    if (size == 0)
        return;
    distance = distance % size;
    if (distance < 0)
        distance += size;
    if (distance == 0)
        return;
    
    for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
        T displaced = list.get(cycleStart);
        int i = cycleStart;
        do {
            i += distance;
            if (i >= size)
                i -= size;
            displaced = list.set(i, displaced);
            nMoved ++;
        } while (i != cycleStart);
    }
}
// 2次反转,负负得正,实现了旋转
private static void rotate2(List<?> list, int distance) {
    int size = list.size();
    if (size == 0)
        return;
    int mid = -distance % size;
    if (mid < 0)
        mid += size;
    if (mid == 0)
        return;
    
    reverse(list.subList(0, mid));
    reverse(list.subList(mid, size));
    reverse(list);
}

 

10、元素替换 replaceAll

  将所有与指定 oldVal 相等的元素替换为新的 newVal

// 将列表中所有是 oldVal 的元素替换为 newVal
// 具体判断就是 (oldVal==null ? e==null : oldVal.equals(e))
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {...}

  

11、子列表匹配

  查找是否存在对应的子列表,并返回相应的下标

// 没有找到或者 target.size() > source.size() 都会返回-1
// BF算法(brute force)实现子列表匹配,返回第1次出现的下标
public static int indexOfSubList(List<?> source, List<?> target) {...}
// BF算法(brute force)实现子列表匹配,返回最后1次出现的下标
public static int lastIndexOfSubList(List<?> source, List<?> target) {...}

  

二、Unmodifiable Wrappers(不可变包装类)

  其实就是将集合包装起来,返回只读的集合包装类,对于变更集合的操作,统一返回 UnsupportedOperationException 。

/**
* 返回指定集合的"只读"的不可变视图,修改操作都会抛出异常 UnsupportedOperationException。
* 该不可变视图没有继承 equals 和 hashCode 方法,使用的是 Object 的。
* 指定的集合是可序列化的话,则返回的视图也是可序列化的
* 内部实现就是在要修改的方法中直接抛出异常。
*/
public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {...}

// "只读" Set 视图,指定的 Set 是可序列化的话,则返回的视图也是可序列化的
public static <T> Set<T> unmodifiableSet(Set<? extends T> s) {...}

// "只读" SortedSet 视图,指定的 SortedSet 是可序列化的话,则返回的视图也是可序列化的
public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s) {...}

// "只读" NavigableSet 视图,指定的 NavigableSet 是可序列化的话,则返回的视图也是可序列化的
public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s) {...}

// "只读" List 视图,指定的 List 是可序列化的话,则返回的视图也是可序列化的;
// 指定的 List 实现了 RandomAccess 的话,视图同样会实现 RandomAccess
public static <T> List<T> unmodifiableList(List<? extends T> list) {...}

// "只读" Map 视图,指定的 Map 是可序列化的话,则返回的视图也是可序列化的
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {...}

// "只读" SortedMap 视图,指定的 SortedMap 是可序列化的话,则返回的视图也是可序列化的
public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m) {...}

// // "只读" NavigableMap 视图,指定的 NavigableMap 是可序列化的话,则返回的视图也是可序列化的
public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m) {...}

 

三、Synch Wrappers(同步安全包装类)

  返回指定集合的线程安全集合包装类,可进行线程安全操作,内部都是通过 synchronized(自身/指定的mutex对象) 实现线程安全,除此外所有操作还是集合本身的常规操作。对于遍历 Iterator/Spliteratoror,还是需要直接指定 synchronized 保证同步。

/**
* 返回指定集合的线程安全集合包装类,可进行线程安全操作
* 内部通过 synchronized (自身/指定的mutex) 实现线程安全,除此外所有操作还是集合本身的常规操作
* 对于遍历 Iterator/Spliteratoror,还是需要直接指定 synchronized 保证同步
* 指定的 Collection 是可序列化的话,则返回的视图也是可序列化的
*/
public static <T> Collection<T> synchronizedCollection(Collection<T> c) {...}
static <T> Collection<T> synchronizedCollection(Collection<T> c, Object mutex) {...}

// 返回线程安全 Set 包装类,其他基本同上
public static <T> Set<T> synchronizedSet(Set<T> s) {...}
static <T> Set<T> synchronizedSet(Set<T> s, Object mutex) {...}

// 返回线程安全 SortedSet 包装类,其他基本同上
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s) {...}

// 返回线程安全 NavigableSet 包装类,其他基本同上
public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) {...}

// 返回线程安全 List 包装类,其他基本同上
public static <T> List<T> synchronizedList(List<T> list) {...}
static <T> List<T> synchronizedList(List<T> list, Object mutex) {...}

// 返回线程安全 Map 包装类,其他基本同上
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {...}

// 返回线程安全 SortedMap 包装类,其他基本同上
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m) {...}

// 返回线程安全 NavigableMap 包装类,其他基本同上
public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) {...}

  

四、Dynamically typesafe collection wrappers(动态类型安全集合包装类)

  返回指定集合/队列的动态类型安全视图。任何插入类型错误的元素的尝试都将立即导致 ClassCastException。假设在动态类型安全视图生成之前,集合不包含类型不正确的元素,并且随后对集合的所有访问都是通过视图进行的,则可以保证集合不能包含类型不正确的元素。

  另外,null 可以被当成任意类型,该视图允许 null。

// Collection
public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) {...}

// Queue
public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {...}

// Set
public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {...}

// SortedSet
public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type) {...}

// NavigableSet
public static <E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s, Class<E> type) {...}

// List
public static <E> List<E> checkedList(List<E> list, Class<E> type) {...}

// Map
public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {...}

// SortedMap
public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType) {...}

// NavigableMap
public static <K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m, Class<K> keyType, Class<V> valueType) {...}

  

五、Empty collections(空集合)

  返回相应的没有元素的空集合。

/**
* 返回没有元素的 Iterator 。更具体点就是
* hasNext 总是返回 false
* next 总是抛出 NoSuchElementException
* remove 总是抛出 IllegalStateException
*/
public static <T> Iterator<T> emptyIterator() {...}

/**
* 返回没有元素的 list iterator。更具体点就是
* hasNext 和 hasPrevious 总是返回 false
* next 和 previous 总是抛出 NoSuchElementException
* remove 和 set always 总是泡池 IllegalStateException.
* add 总是抛出 UnsupportedOperationException
* nextIndex 总是返回 0
* previousIndex 总是返回 -1
*/
public static <T> ListIterator<T> emptyListIterator() {...}

/**
* 返回没有元素的 enumeration
* hasMoreElements 总是返回 false.
* nextElement 总是抛出 NoSuchElementException.
*/
public static <T> Enumeration<T> emptyEnumeration() {...}

// 没有元素的 Set
public static final <T> Set<T> emptySet() {...}

// 没有元素的 SortedSet
public static <E> SortedSet<E> emptySortedSet() {...}

// 没有元素的 NavigableSet
public static <E> NavigableSet<E> emptyNavigableSet() {...}

// 没有元素的 List
public static final <T> List<T> emptyList() {...}

// 没有元素的 Map
public static final <K,V> Map<K,V> emptyMap() {...}

// 没有元素的 SortedMap
public static final <K,V> SortedMap<K,V> emptySortedMap() {...}

// 没有元素的 NavigableMap
public static final <K,V> NavigableMap<K,V> emptyNavigableMap() {...}

  

六、Singleton collections(单例集合)

  单例集合,说的是只包含一个指定元素对象的不可变集合。

// 返回只包含1个指定对象元素的不可变 Set,且事序列化的
public static <T> Set<T> singleton(T o) {...}

// Iterator
static <E> Iterator<E> singletonIterator(final E e) {...}

// Spliterator
static <T> Spliterator<T> singletonSpliterator(final T element) {...}

// 不可变的 List
public static <T> List<T> singletonList(T o) {...}

// 不可变的 Map
public static <K,V> Map<K,V> singletonMap(K key, V value) {...}

  

七、Miscellaneous(杂项/其他)

  其他一些操作如下:

// 返回包含指定元素对象 n 分拷贝的不可变 List,其实内部只保留了引用和 n,并非真正的 n 份
public static <T> List<T> nCopies(int n, T o) {...}

// 返回 反向排序的 Comparator,即 Comparable 接口自然排序的反向排序
// 例子:Arrays.sort(a, Collections.reverseOrder());
public static <T> Comparator<T> reverseOrder() {

// 返回指定 Comparator 的反向排序 Comparator,如果为null,则相当于 reverseOrder()
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {...}

// 返回指定集合上的枚举。这提供了与需要枚举作为输入的遗留api的互操作性。
public static <T> Enumeration<T> enumeration(final Collection<T> c) {...}

// 返回一个数组列表,其中包含由指定枚举返回的元素,其顺序与枚举返回元素的顺序相同。
// 此方法提供了返回枚举的遗留api与需要集合的新api之间的互操作性。
public static <T> ArrayList<T> list(Enumeration<T> e) {...}

// 指定元素对象在集合的出现频率
// o == null ? e == null : o.equals(e)
public static int frequency(Collection<?> c, Object o) {...}

// 2个集合没有交集就返回 true
public static boolean disjoint(Collection<?> c1, Collection<?> c2) {...}

// 添加指定的元素列表的集合中
public static <T> boolean addAll(Collection<? super T> c, T... elements) {...}

// 为 Map 提供对应的 Set 视图,内部其实事使用 map 和 map.eySet() 来进行操作
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {...}

// 为 Deque 提供对应的 Queue 视图
public static <T> Queue<T> asLifoQueue(Deque<T> deque) {...}

 

以上是关于Java8集合框架——集合工具类Collections内部方法浅析的主要内容,如果未能解决你的问题,请参考以下文章

Collectio集合,List《ArrayList,LinkedList》

总结集合框架的关系

Java8集合框架——HashSet源码分析

StringUtilsCollectionUtils工具类的常用方法

20170824 - A - 集合框架

集合框架工具类Collections