Collections 包含用于操作集合的各种方法。
Collections 也提供了 sort() 和 binarySearch,sort() 底层使用的就是 Arrays.sort(),binarySearch() 底层使用的是自己重写的二分查找算法,实现逻辑和 Arrays.binarySearch() 完全一致。

求集合中最大值 & 最小值

max() 取集合中最大值,min() 取集合中最小值。
max 提供了两种类型的方法,一个需要传外部排序器,一个不需要传排序器,但需要集合中的元素强制实现 Comparable 接口
max() 的底层源码实现如下:

  1. public static <T> T max(Collection<? extends T> coll,
  2. Comparator<? super T> comp) {
  3. if (comp==null)
  4. return (T)max((Collection) coll);
  5. Iterator<? extends T> i = coll.iterator();
  6. T candidate = i.next();
  7. while (i.hasNext()) {
  8. T next = i.next();
  9. if (comp.compare(next, candidate) > 0)
  10. candidate = next;
  11. }
  12. return candidate;
  13. }
  1. public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
  2. Iterator<? extends T> i = coll.iterator();
  3. // 最大值的候选人
  4. T candidate = i.next();
  5. while (i.hasNext()) {
  6. T next = i.next();
  7. if (next.compareTo(candidate) > 0)
  8. candidate = next;
  9. }
  10. return candidate;
  11. }

从 max() 源码中,我们可以学习到两点:

  • 给我们提供了实现两种排序机制的好示例:自定义类实现 Comparable 接口和传入外部排序
    器。两种排序实现原理类似,但实现有所差别,如果需要写排序的工具类时,可以效仿
  • max() 泛型 T 定义得非常巧妙,意思是:泛型必须继承 Object 并且实现 Comparable 的接口

    一般让我们来定义的话,我们可以会在方法里面去判断有无实现 Comparable 的接口,这种是在运行时才能知道结果。 而这里泛型直接定义了必须实现 Comparable 接口,在编译的时候就可告诉使用者,当前类有没有实现 Comparable 接口,使用起来很友好。

多种类型的集合

Collections 对原始集合类进行了封装,提供了更好的集合类给我们,一种是线程安全的集合,一种是不可变的集合。
以下两种 List 其实解决了工作中的一些困惑,比如说 ArrayList 是线程不安全的,然后其内部数组很容易被修改,有时,我们希望 List 一旦生成后,就不能被修改,Collections 对 List 重新进行了封装,提供了两种类型的集合封装形式,从而解决了工作中的一些烦恼,如果你平时使用 List 时有一些烦恼,也可以学习此种方式,自己对原始集合进行封装,来解决 List 使用过程中的不方便。


线程安全的集合

线程安全的集合中方法都是 synchronized 打头的,底层是通过 synchronized 轻量锁来实现的 ,以 synchronizedList 为例来说明底层的实现

  1. static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
  2. private static final long serialVersionUID = -7754090372962971524L;
  3. // 这个 List 就是我们需要保证线程安全的集合
  4. final List<E> list;
  5. SynchronizedList(List<E> list) {
  6. super(list);
  7. this.list = list;
  8. }
  9. SynchronizedList(List<E> list, Object mutex) {
  10. super(list, mutex);
  11. this.list = list;
  12. }
  13. public boolean equals(Object o) {
  14. if (this == o)
  15. return true;
  16. synchronized (mutex) {return list.equals(o);}
  17. }
  18. public int hashCode() {
  19. synchronized (mutex) {return list.hashCode();}
  20. }
  21. public E get(int index) {
  22. synchronized (mutex) {return list.get(index);}
  23. }
  24. public E set(int index, E element) {
  25. synchronized (mutex) {return list.set(index, element);}
  26. }
  27. public void add(int index, E element) {
  28. synchronized (mutex) {list.add(index, element);}
  29. }
  30. public E remove(int index) {
  31. synchronized (mutex) {return list.remove(index);}
  32. }
  33. public int indexOf(Object o) {
  34. synchronized (mutex) {return list.indexOf(o);}
  35. }
  36. public int lastIndexOf(Object o) {
  37. synchronized (mutex) {return list.lastIndexOf(o);}
  38. }
  39. public boolean addAll(int index, Collection<? extends E> c) {
  40. synchronized (mutex) {return list.addAll(index, c);}
  41. }
  42. public ListIterator<E> listIterator() {
  43. return list.listIterator(); // Must be manually synched by user
  44. }
  45. public ListIterator<E> listIterator(int index) {
  46. return list.listIterator(index); // Must be manually synched by user
  47. }
  48. public List<E> subList(int fromIndex, int toIndex) {
  49. synchronized (mutex) {
  50. return new SynchronizedList<>(list.subList(fromIndex, toIndex),
  51. mutex);
  52. }
  53. }
  54. @Override
  55. public void replaceAll(UnaryOperator<E> operator) {
  56. synchronized (mutex) {list.replaceAll(operator);}
  57. }
  58. @Override
  59. public void sort(Comparator<? super E> c) {
  60. synchronized (mutex) {list.sort(c);}
  61. }
  62. /**
  63. * SynchronizedRandomAccessList instances are serialized as
  64. * SynchronizedList instances to allow them to be deserialized
  65. * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
  66. * This method inverts the transformation. As a beneficial
  67. * side-effect, it also grafts the RandomAccess marker onto
  68. * SynchronizedList instances that were serialized in pre-1.4 JREs.
  69. *
  70. * Note: Unfortunately, SynchronizedRandomAccessList instances
  71. * serialized in 1.4.1 and deserialized in 1.4 will become
  72. * SynchronizedList instances, as this method was missing in 1.4.
  73. */
  74. private Object readResolve() {
  75. return (list instanceof RandomAccess
  76. ? new SynchronizedRandomAccessList<>(list)
  77. : this);
  78. }
  79. }

可以看到 List 的所有操作方法都被加上了 synchronized 锁,所以多线程对集合同时进行操作,是线程安全的。


不可变的集合

不可变的集合,只开放了查询方法,其余任何修改操作都会抛出异常。
以 unmodifiableList 为例来说明底层的实现:

  1. static class UnmodifiableList<E> extends UnmodifiableCollection<E> implements List<E> {
  2. private static final long serialVersionUID = -283967356065247728L;
  3. final List<? extends E> list;
  4. UnmodifiableList(List<? extends E> list) {
  5. super(list);
  6. this.list = list;
  7. }
  8. public boolean equals(Object o) {return o == this || list.equals(o);}
  9. public int hashCode() {return list.hashCode();}
  10. public E get(int index) {return list.get(index);}
  11. public E set(int index, E element) {
  12. throw new UnsupportedOperationException();
  13. }
  14. public void add(int index, E element) {
  15. throw new UnsupportedOperationException();
  16. }
  17. public E remove(int index) {
  18. throw new UnsupportedOperationException();
  19. }
  20. public int indexOf(Object o) {return list.indexOf(o);}
  21. public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
  22. public boolean addAll(int index, Collection<? extends E> c) {
  23. throw new UnsupportedOperationException();
  24. }
  25. @Override
  26. public void replaceAll(UnaryOperator<E> operator) {
  27. throw new UnsupportedOperationException();
  28. }
  29. @Override
  30. public void sort(Comparator<? super E> c) {
  31. throw new UnsupportedOperationException();
  32. }
  33. public ListIterator<E> listIterator() {return listIterator(0);}
  34. public ListIterator<E> listIterator(final int index) {
  35. return new ListIterator<E>() {
  36. private final ListIterator<? extends E> i
  37. = list.listIterator(index);
  38. public boolean hasNext() {return i.hasNext();}
  39. public E next() {return i.next();}
  40. public boolean hasPrevious() {return i.hasPrevious();}
  41. public E previous() {return i.previous();}
  42. public int nextIndex() {return i.nextIndex();}
  43. public int previousIndex() {return i.previousIndex();}
  44. public void remove() {
  45. throw new UnsupportedOperationException();
  46. }
  47. public void set(E e) {
  48. throw new UnsupportedOperationException();
  49. }
  50. public void add(E e) {
  51. throw new UnsupportedOperationException();
  52. }
  53. @Override
  54. public void forEachRemaining(Consumer<? super E> action) {
  55. i.forEachRemaining(action);
  56. }
  57. };
  58. }
  59. public List<E> subList(int fromIndex, int toIndex) {
  60. return new UnmodifiableList<>(list.subList(fromIndex, toIndex));
  61. }
  62. /**
  63. * UnmodifiableRandomAccessList instances are serialized as
  64. * UnmodifiableList instances to allow them to be deserialized
  65. * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList).
  66. * This method inverts the transformation. As a beneficial
  67. * side-effect, it also grafts the RandomAccess marker onto
  68. * UnmodifiableList instances that were serialized in pre-1.4 JREs.
  69. *
  70. * Note: Unfortunately, UnmodifiableRandomAccessList instances
  71. * serialized in 1.4.1 and deserialized in 1.4 will become
  72. * UnmodifiableList instances, as this method was missing in 1.4.
  73. */
  74. private Object readResolve() {
  75. return (list instanceof RandomAccess
  76. ? new UnmodifiableRandomAccessList<>(list)
  77. : this);
  78. }
  79. }