起因:工作中需要對(duì)集合進(jìn)行一個(gè)亂序的重排序,當(dāng)時(shí)不太記得Collections中的方法,去百度了一下,發(fā)現(xiàn)Collections工具類提供了相應(yīng)的方法陕截,之前有用過(guò)Collections其中的一些方法,但是沒(méi)有對(duì)其API有一個(gè)系統(tǒng)的學(xué)習(xí)和記錄批什,這次記錄一下农曲。知道這里有了,用的時(shí)候也好找了驻债。
Collections是 JDK提供的工具類乳规,提供了一系列靜態(tài)方法,方便操作各種集合合呐。分析和總結(jié)一下其API暮的,記錄一下。
Collections主要有以下幾個(gè)功能
- 排序
- 亂序(洗牌)
- 替換
- 創(chuàng)建空集合
- 創(chuàng)建單元集合
- 不可變集合
- 線程安全集合
接下來(lái)稍微介紹一下相關(guān)操作與demo淌实,其實(shí)看api更好冻辩。
1.排序
- reverse(List list):反轉(zhuǎn)指定List集合中元素的順序
- shuffle(List list):對(duì)List中的元素進(jìn)行隨機(jī)排序(洗牌)
- sort(List list):對(duì)List里的元素根據(jù)自然升序排序
- sort(List list, Comparator c):自定義比較器進(jìn)行排序
- swap(List list, int i, int j):將指定List集合中i處元素和j出元素進(jìn)行交換
- rotate(List list, int distance):將所有元素向右移位指定長(zhǎng)度,如果distance等于size那么結(jié)果不變
Collections可以對(duì)List進(jìn)行sort排序拆祈。因?yàn)榕判驎?huì)直接修改List元素的位置恨闪,因此必須傳入可變List。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("pear");
list.add("orange");
// 排序前:
System.out.println(list);
Collections.sort(list);
// 排序后:
System.out.println(list);
}
排序也是有講究的放坏。列表中的所有元素必須實(shí)現(xiàn)Comparable接口
,因?yàn)樽罱K還是要根據(jù)Comparable中的方法來(lái)對(duì)其實(shí)施排序咙咽。以下是JDK源碼。
除了默認(rèn)排序還有自定義排序淤年,自定義排序需要傳入Comparator比較器犁珠。一般使用compare(T o1, T o2)方法就可以了,比較常用的還有reversed()方法互亮,到排序。詳情見(jiàn)我的另一篇余素,排序豹休!
//默認(rèn)排序
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);
}
2.亂序(洗牌)
Collections提供了洗牌算法,即傳入一個(gè)有序的List桨吊,可以隨機(jī)打亂List內(nèi)部元素的順序威根,效果相當(dāng)于讓計(jì)算機(jī)洗牌:
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i=0; i<10; i++) {
list.add(i);
}
// 洗牌前:
System.out.println(list);
Collections.shuffle(list);
// 洗牌后:
System.out.println(list);
}
排序其實(shí)就是拿到傳入的list凤巨,然后對(duì)任意兩個(gè)元素交換位置,也可以傳入一個(gè)帶隨機(jī)數(shù)的洛搀,沒(méi)看源碼敢茁,有空可以了解一下。
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
private static Random r;
//--------------------------------------
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
// 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
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
//--------------------------------------
private static void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
3. 查找和替換
- binarySearch(List list, Object key):使用二分搜索法留美,以獲得指定對(duì)象在List中的索引彰檬,前提是集合已經(jīng)排序
- max(Collection coll):返回最大元素
- max(Collection coll, Comparator comp):根據(jù)自定義比較器,返回最大元素
- min(Collection coll):返回最小元素
- min(Collection coll, Comparator comp):根據(jù)自定義比較器谎砾,返回最小元素
- fill(List list, Object obj):使用指定對(duì)象填充
- frequency(Collection Object o):返回指定集合中指定對(duì)象出現(xiàn)的次數(shù)
- replaceAll(List list, Object old, Object new):替換
4.創(chuàng)建空集合
Collections提供了一系列方法來(lái)創(chuàng)建空集合:
創(chuàng)建空List:List<T> emptyList()
創(chuàng)建空Map:Map<K, V> emptyMap()
創(chuàng)建空Set:Set<T> emptySet()
要注意到返回的空集合是不可變集合逢倍,無(wú)法向其中添加或刪除元素。
此外景图,也可以用各個(gè)集合接口提供的of(T...)方法創(chuàng)建空集合较雕。例如,以下創(chuàng)建空List的兩個(gè)方法是等價(jià)的:
List<String> list1 = List.of();
List<String> list2 = Collections.emptyList();
創(chuàng)建新的集合現(xiàn)在都在用Guava 的Lists.asList(),之后再記錄一下
public static <E> List<E> asList(@Nullable E first, E[] rest) {
return new OnePlusArrayList<E>(first, rest);
}
5.創(chuàng)建單元素集合
Collections提供了一系列方法來(lái)創(chuàng)建一個(gè)單元素集合:
創(chuàng)建一個(gè)元素的List:List<T> singletonList(T o)
創(chuàng)建一個(gè)元素的Map:Map<K, V> singletonMap(K key, V value)
創(chuàng)建一個(gè)元素的Set:Set<T> singleton(T o)
要注意到返回的單元素集合也是不可變集合挚币,無(wú)法向其中添加或刪除元素亮蒋。
此外,也可以用各個(gè)集合接口提供的of(T...)方法創(chuàng)建單元素集合妆毕。例如慎玖,以下創(chuàng)建單元素List的兩個(gè)方法是等價(jià)的:
List<String> list1 = List.of("apple");
List<String> list2 = Collections.singletonList("apple");
實(shí)際上,使用List.of(T...)更方便设塔,因?yàn)樗瓤梢詣?chuàng)建空集合凄吏,也可以創(chuàng)建單元素集合,還可以創(chuàng)建任意個(gè)元素的集合:
List<String> list1 = List.of(); // empty list
List<String> list2 = List.of("apple"); // 1 element
List<String> list3 = List.of("apple", "pear"); // 2 elements
List<String> list4 = List.of("apple", "pear", "orange"); // 3 elements
6.不可變集合
Collections還提供了一組方法把可變集合封裝成不可變集合:
封裝成不可變List:List<T> unmodifiableList(List<? extends T> list)
封裝成不可變Set:Set<T> unmodifiableSet(Set<? extends T> set)
封裝成不可變Map:Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m)
這種封裝實(shí)際上是通過(guò)創(chuàng)建一個(gè)代理對(duì)象闰蛔,攔截掉所有修改方法實(shí)現(xiàn)的痕钢。類似與Guava 的ImmutableMap
我的另一篇Guava 的ImmutableMap
7.線程安全集合
自從有了juc,基本沒(méi)啥用序六,就不寫了任连。
不要以為每天把功能完成了就行了,這種思想是要不得的例诀,互勉~随抠!