===========
Collection是集合的最顶层接口,提供了对集合对象进行基本操作的通用接口方法。为各种具体的集合提供了最大化的统一操作方式。
Collentions是一个工具类。它包含各种有关集合操作的静态多态方法,此类的构造方法为private,不能被实例化。
基于Java 9
根据是否有返回值 可以把Collections工具类的方法
大体上分为两类 一组是返回集合对象的方法
另一组是对传入的集合对象操作的方法
**这些方法都返回一个重新包装的集合对象 也称之为视图对象
提供了许多重要功能 减少了繁琐的数据结构构建开销**
空集合指的是没有元素在这些集合中,特别需要主要的是返回的集合都是只读的。只要更改值就会抛出UnsupportedOperationException异常 如果获取元素则抛出下标越界异常
Collections.EMPTY_LIST,Collections.emptyList()//返回只读 的空LIST 集合 Collections.EMPTY_MAP,Collections.emptyMap()//返回只读 的空MAP集合 Collections.EMPTY_SET,Collections.emptySet()//返回只读 的空SET集合其实底层有一个Empty*类,就是返回一个新的实例。
看源码 以emptyList为例
返回一个内部类 EmptyList public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; }EmptyList和ArrayList 一样 都实现了RandomAccess接口 扩展AbstractList抽象类不一样的是EmptyList内部没有实际的数据序列所有方法都返回空或者0 private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialVersionUID = 8842843931221139166L; ……空集合主要用于一些需要返回集合的场合
传统的 返回一个新的集合或者匿名集合 无形中增加了内存占用
return new ArrayList<T>();而返回空集合
return Collections.emptyList();由源码可知是Collections类的一个static内部类的引用 无论有多少个引用 所占内存都是一样的
单元素集合Collections中的单元素集合指的是集合只有一个元素而且集合只读。
Collections.singletonList //用来生成只读 的单一元素的List Collections.singletonMap //用来生成只读 的单Key和Value组成的Map Collections.singleton //用来生成只读 的单一元素的Set创建一个String泛型限定的单一元素集合
String string="This is a string"; List<String> list=Collections.singletonList(string);此单元素集合不能新增 移除元素 否则会抛出异常
其实底层有一个singleton*类,调用方法就返回一个实例
源码 SingletonList为例
private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialVersionUID = 3093736618740652951L; 相比空集合 单元素集合有了实际的数据序列 private final E element; …… }单元素集合同样实现了RandomAccess接口 扩展AbstractList抽象类
但是重写的集合方法 不支持所有对集合对象的改变操作
运用单元素集合 可以便捷的从集合中移除重复元素
示例
List<String> list = new ArrayList<String>();list.add("abc");list.add(null);list.add("def");list.removeAll(Collections.singletonList(null));System.out.println(list); //[abc, def]这些集合一旦初始化以后就不能修改,任何修改这些集合的方法都会抛出UnsupportedOperationException异常。
Collections.unmodifiableCollection()Collections.unmodifiableList()Collections.unmodifiableMap() Collections.unmodifiableSet() Collections.unmodifiableSortedMap() Collections.unmodifiableSortedSet()以上方法都顾名思义
创建一个只读的链表
List list=new LinkedList<String>();List unmodList=Collections.unmodifiableList(list);unmodList就成为一个被构建出来的只读集合 unmodList等只读集合内部引用了原始集合
对外提供的是自己的方法 保证不能修改原集合
但是 如果修改了原始集合 则此只读集合也会改变 类似Arrays.asList()
Checked集合Checked集合具有检查插入集合元素类型的特性,例如当我们设定checkedList中元素的类型是String的时候,如果插入起来类型的元素就会抛出ClassCastExceptions异常。
Collections.checkedCollection()Collections.checkedList() Collections.checkedMap() Collections.checkedSortedMap() Collections.checkedSortedSet()Collections.checkedNavigableSet() Collections.checkedNavigableSet()以上方法都顾名思义
示例
List<Integer> integerList=new ArrayList<>(); List checkedlist=Collections.checkedList(integerList,Integer.class);此时 checkedlist不能插入非Integer类型 否则报ClassCastException
同步集合Collections.synchronizedCollection()Collections.synchronizedList() Collections.synchronizedMap() Collections.synchronizedSortedMap() Collections.synchronizedSortedSet()Collections.synchronizedNavigableMap()Collections.synchronizedNavigableSet()Collections的synchronizedXxxxx系列方法顾名思义会返回同步化集合类(SynchronizedMap,
SynchronizedList等等)。
这些集合类内部实现都是通过一个mutex(互斥体)来实现对这些集合操作的同步化。
保证了多线程并发安全
synchronizedList 可以代替过时的Vector向量类
当然同样的CopyOnWriteArrayList 也可以代替Vector向量类
Collections.synchronizedList() 包装方法返回的同步列表在写操作上更快
而CopyOnWriteArrayList在读操作上更迅速
另外 如果你需要一个并发安全的LinkedList 那么显然只能使用synchronizedList()
Collections.synchronizedMap()方法可以代替过时的HashTable类
当然 现在更推荐的是使用改进的并发散列表ConcurrentHashMap
来代替过时的 HashTable类
public static <T> void fill(List<? super T> list, T obj) { int size = list.size(); if (size < FILL_THRESHOLD || list instanceof RandomAccess) { for (int i=0; i<size; i++) list.set(i, obj); } else { ListIterator<* super T> itr = list.listIterator(); for (int i=0; i<size; i++) { itr.next(); itr.set(obj); } }}Collections.fill(List< ? super T> list, T obj)
这里可以看出有一个域值FILL_THRESHOLD,这个值为25,如果小于25,或者实现随机访问接口的,直接set。否则使用迭代器的set。
List<String> stringList=new ArrayList<>(10); …… Collections.fill(stringList,"fill string");注意 Collections.fill()方法只会填充list的实际size大小的数据
frequency()方法 返回指定 collection 中等于指定对象的元素数
public static int frequency(Collection<?> c, Object o) { int result = 0; if (o == null) { for (Object e : c) if (e == null) result++; } else { for (Object e : c) if (o.equals(e)) result++; } return result;}Collections.frequency(Collection< ? > c, Object o)
为null的时候用==判断,否则用equals(Object中equals也是用的==判断)。
返回指定源列表中指定元素位置public static int indexOfSubList(List<?> source, List<?> target) { int sourceSize = source.size(); int targetSize = target.size(); int maxCandidate = sourceSize - targetSize; 如果列表大小小于35或者列表支持随机访问 if (sourceSize < INDEXOFSUBLIST_THRESHOLD || (source instanceof RandomAccess&&target instanceof RandomAccess)) { nextCand: for (int candidate = 0; candidate <= maxCandidate; candidate++) { for (int i=0, j=candidate; i<targetSize; i++, j++) if (!eq(target.get(i), source.get(j))) continue nextCand; // 元素未匹配到 回退到起始位置 return candidate; // 所有元素比较完毕 } } else { 不支持随机访问 使用迭代器遍历 ListIterator<?> si = source.listIterator(); nextCand: for (int candidate = 0; candidate <= maxCandidate; candidate++) { ListIterator<?> ti = target.listIterator(); for (int i=0; i<targetSize; i++) { if (!eq(ti.next(), si.next())) { //回退原列表迭代器到起始位置 for (int j=0; j<i; j++) si.previous(); continue nextCand; } } return candidate; } }Collections.indexOfSubList(List< ? > source, List< ? > target)
Collections.lastIndexOfSubList(List< ? > source, List< ? > target)
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) { if (comp==null) return (T)max((Collection) coll); Iterator<? extends T> i = coll.iterator(); T candidate = i.next(); while (i.hasNext()) { T next = i.next(); if (comp.compare(next, candidate) > 0) candidate = next; } return candidate;}Collections.max(Collection< ? extends T> coll, Comparator< ? super T> comp)
Collections.min(Collection< ? extends T> coll, Comparator< ? super T> comp)
max,min方法显然需要排序 如果集合中的对象没有实现comparator接口,
就以自然顺序排序,如果显示的制指定了Comparator比较器
则使用比较器提供的比较方法比较
注:comparable和comparator的区别。
Comparator在util包下,Comparable在lang包下。
java中的对象排序都是以comparable接口为标准的。
comparator是在对象外部实现排序。
Collections.replaceAll(List list, T oldVal, T newVal)
原理也和其他类似 先迭代比较 再替换
public static void reverse(List<?> list) { int size = list.size(); if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) { for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--) swap(list, i, j); } else { ListIterator fwd = list.listIterator(); ListIterator rev = list.listIterator(size); for (int i=0, mid=list.size()>>1; i<mid; i++) { Object tmp = fwd.next(); fwd.set(rev.previous()); rev.set(tmp); } }}Collections.reverse(List< ? > list)
都是分为两种情况进行处理,支持随机访问的使用swap首尾交换
使用迭代器的需要两个迭代器,一个前向迭代 一个后向迭代
使用中间值进行交换
Collections.shuffle(List< ? > list)
public static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null);}public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c);}Collections.sort(List list)
Collections.sort(List list, Comparator
sort方法底层其实就是调用List接口的sort方法
java8中List接口使用default关键字实现了sort方法
使用sort方法可以对指定列表按升序进行排序。
如果没有指定比较器Comparator,则列表中的所有元素都必须实现Comparable接口
否则会使用自然顺序进行排序
也可以 使用Collections.sort(List list, Comparator
default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); }}发现其实底层是调用的Arrays.sort()方法,然后调用迭代器给现在的list赋值。
其他Collections.reverseOrder(Comparator cmp)
返回一个和入参的 Comparator cmp比较器 反向的比较器
public static <T> void copy(List<? super T> dest, List<? extends T> src) { int srcSize = src.size(); if (srcSize > dest.size()) throw new IndexOutOfBoundsException("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) { for (int i=0; i<srcSize; i++) dest.set(i, src.get(i)); } else { ListIterator<? super T> di=dest.listIterator(); ListIterator<? extends T> si=src.listIterator(); for (int i=0; i<srcSize; i++) { di.next(); di.set(si.next()); } } }Collections.copy(List< ? super T> dest, List< ? extends T> src)
public static void swap(List<?> list, int i, int j) { final List l = list; l.set(i, l.set(j, l.get(i))); 巧妙的利用了List实现类的set新值返回旧值的功能}private static void swap(Object[] arr, int i, int j) { 对于数组 只能中值交换了 Object tmp = arr; arr = arr[j]; arr[j] = tmp;}Collections.sort()
同样,对于链表和数组有不同的操作方式。
Collections.rotate(List< ? > list, int distance)
假设list包含[t, a, b, k, s]。
在调用Collection.rotate(list, 1)
或者 Collection.rotate(list, -4) 后
list将包含[s, t, a, b, k]。
代码示例
List<String> stringList=new ArrayList<>(10); stringList.add("a"); stringList.add("b"); stringList.add("c"); stringList.add("e"); stringList.add("f"); System.out.println(Arrays.deepToString(stringList.toArray())); //[a, b, c, e, f] Collections.rotate(stringList,2); System.out.println(Arrays.deepToString(stringList.toArray())); //[e, f, a, b, c]Collections.addAll(Collection<* super T> c, T… elements);
显然这个方法 只能是实现了Collection接口的列表才能使用
List<String> stringList=new ArrayList<>(10); stringList.add("a"); stringList.add("b"); stringList.add("c"); stringList.add("e"); stringList.add("f"); //stringList.add("g"); stringList.add("h"); int a=Collections.binarySearch(stringList,"a"); int b=Collections.binarySearch(stringList,"b"); int i=Collections.binarySearch(stringList,"i"); System.out.println(a); System.out.println(b); System.out.println(g); System.out.println(i); //0 //1 //-6 //-7Collections.binarySearch(List< ? extends Comparable< ? super T>> list, T key)
Collections.binarySearch(List< ? extends T> list, T key, Comparator< ? super T> c)
这个方法只能是实现了Collection接口的列表才能使用
Collections.List nCopies(int n, T o)
N倍复制方法 返回一个包含有N个入参的集合对象的新集合
当然 这个新集合也是不可变的
示例
List<List<String>> anotherList=Collections.nCopies(5,stringList); anotherList.forEach(x-> System.out.println(x)); System.out.println(anotherList.size());这个类很巧妙 其实只保存了一个element对象 和复制倍数n
调用get方法时永远返回element对象
List<String> stringList=new ArrayList<>(10); stringList.add("a"); stringList.add("b"); stringList.add("c"); stringList.add("e"); stringList.add("f"); stringList.add("g"); stringList.add("h"); boolean bp=Collections.disjoint(stringList,stringList); //false List list=new LinkedList(); boolean bp2=Collections.disjoint(list,list); //trueCollections.disjoint(Collection< ? > c1, Collection< ? > c2)
两个含有相同元素的的集合 disjoin返回false 说明不互斥 存在交集
注意 而两个空集合 disjoin返回true
list()方法 枚举对象转为数组列表
Collections.list(Enumeration e)
不常用方法 主要是Enumeration类功能已经被迭代器替代了
主要用于一些遗留Enumeration对象的场合
newSetFormMap()方法 根据指定的map对象创建对应的Set对象
Collections.newSetFromMap(Map< E, Boolean> map)
众所周知 set就是个套着马甲的Map 例如TreeMap和HashMap
这些Set类都是基于对应的Map类实现的
因此它们和对应的Map类保持相同的算法复杂度以及并发特性。
所以可以使用此方法来创建对应的Set对象
Java 7 以后提供了更安全的并发散列表concurrentHashMap
但是并没有对应的set
可以自己创建一个
Set concurrentHashSet=Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>());
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |