前言
? ? ? ? 早期開發者經常需要對集合進行各種操作
? ? ? ? 比如排序、查找最大最小值等等
? ? ? ? 但是當時沒有統一的工具類來處理
? ? ? ? 所以導致代碼重復且容易出錯
????????
? ? ? ? java.util.Collections 工具類的引入
? ? ? ? 為開發者提供了大量?靜態方法?來操作集合
? ? ? ? 它就像一個經驗豐富的助手
? ? ? ? 和數組工具類 Arrays 一樣
? ? ? ? 避免了我們重復造輪子的情況
一、Collections 工具類概述
java.util.Collections 是一個操作集合的工具類
提供大量 靜態方法 來 操作 或 返回 集合
源碼:
// Collections 類的聲明
public class Collections {// 私有構造函數,防止實例化private Collections() {}// ... 大量靜態方法
}
通過源碼我們可以看出:
- Collections 是一個很純粹的工具類
- 沒有繼承,沒有實現,父類是 Object
- 構造器私有,不能實例化對象?
注意區分:
? ? ? ? Collections 是集合的工具類
? ? ? ? Collection? ?是單列集合的根接口
二、核心方法
1、addAll
方法聲明:
????????public static <T> boolean addAll(Collection<? super T> c, T... elements)
調用者:
????????Collections
參數:
????????Collection<? super T>c :目標集合
? ? ? ? T...elements :要添加的元素(可變參)
? ? ? ?
泛型中,我們常見三種形式:
1、T? ? ? ? ? ? ? ? ? ? ? ? 具體類型參數
2、?extends T? ? ? 上界通配符,表示T或T的子類型
3、?super T? ? ? ? ? 下界通配符,表示T或T的父類型
????????????????????????
返回值:
????????boolean,如果集合被修改則返回true
作用:
????????將多個元素一次性添加到集合中
是否改變原始值:
????????是,會修改目標集合
源碼:
public static <T> boolean addAll(Collection<? super T> c, T... elements) {boolean result = false;for (T element : elements)result |= c.add(element);return result;
}
源碼解讀:
- 使用可變參 T...elements 接收任意數量的元素
- 遍歷所有元素,逐個添加到集合中
- 使用 位或運算 |= 累計添加結果,只要有元素成功添加就返回true
示例:
import java.util.*;public class AddAllExample {public static void main(String[] args) {List<String> fruits = new ArrayList<>();// 使用 Collections.addAll 批量添加元素Collections.addAll(fruits, "apple", "banana", "orange", "grape");System.out.println("水果列表: " + fruits);// 輸出: 水果列表: [apple, banana, orange, grape]// 對比傳統方式List<String> vegetables = new ArrayList<>();vegetables.add("carrot");vegetables.add("potato");vegetables.add("tomato");System.out.println("蔬菜列表: " + vegetables);// 輸出: 蔬菜列表: [carrot, potato, tomato]}
}
2、sort
方法聲明:
? ? ? ? //自然排序版本
????????public static <T extends Comparable<? super T>> void sort(List<T> list)
? ? ? ? //比較器排序版本
????????public static <T> void sort(List<T> list, Comparator<? super T> c)
調用者:
? ? ? ? Collections
參數:
? ? ? ? List<T> list:要排序的列表
? ? ? ? Comparator<?super T>c:比較器(可選)
返回值:
? ? ? ? void
作用:
? ? ? ? 對列表進行排序
是否改變原始值:
? ? ? ? 是,會修改原列表
注意事項:
? ? ? ? 自然排序要求實現 Comparable 接口
源碼:
// 自然排序版本
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);
}
源碼解讀:
實際上是委托給 List 接口的 sort 方法實現
JDK 8 之后,List 接口增加了默認方法 sort,Collections.sort 成為了該方法的包裝
JDK 8 之前 Collections.sort() 實現:
// JDK 8 之前的 Collections.sort() 實現(簡化版) public static <T extends Comparable<? super T>> void sort(List<T> list) {Object[] a = list.toArray();Arrays.sort(a);ListIterator<T> i = list.listIterator();for (int j=0; j<a.length; j++) {i.next();i.set((T)a[j]);} }
JDK 8 之后 List 接口新增的默認方法:
// List 接口中的默認方法 sort() default void sort(Comparator<? super E> c) {Object[] a = this.toArray();Arrays.sort(a, (Comparator) c);ListIterator<E> i = this.listIterator();for (int j=0; j<a.length; j++) {i.next();i.set((E) a[j]);} }
JDK 8 之后 Collections.sort() 實現:
// JDK 8 之后 Collections.sort() 的實現(簡化版) public static <T extends Comparable<? super T>> void sort(List<T> list) {list.sort(null); // 委托給 List.sort() 方法 }public static <T> void sort(List<T> list, Comparator<? super T> c) {list.sort(c); // 委托給 List.sort() 方法 }
總結一下:
- 功能轉移:排序核心功能被轉移到了 List 接口中
- 實現委托:Collections.sort() 方法現在內部調用 List.sort() 來實現排序功能
示例:
import java.util.*;public class SortExample {public static void main(String[] args) {// 自然排序示例List<Integer> numbers = new ArrayList<>();Collections.addAll(numbers, 5, 2, 8, 1, 9);System.out.println("排序前: " + numbers);Collections.sort(numbers); // 自然排序System.out.println("自然排序后: " + numbers);// 輸出: 自然排序后: [1, 2, 5, 8, 9]// 比較器排序示例(降序)List<String> words = new ArrayList<>();Collections.addAll(words, "banana", "apple", "cherry");System.out.println("排序前: " + words);Collections.sort(words, Collections.reverseOrder()); // 降序排序System.out.println("降序排序后: " + words);// 輸出: 降序排序后: [cherry, banana, apple]}
}
3、reverse
方法聲明:
????????public static void reverse(List<?> list)
調用者:
? ? ? ? Collections
參數:
? ? ? ? List<?> list :要反轉的列表?
返回值:
? ? ? ? void
作用:
? ? ? ? 反轉集合中的元素順序
是否改變原始值:
? ? ? ? 是,會修改原集合
注意事項:
? ? ? ? 只適用于 List 類型的集合
源碼:
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 {// 對于大列表且非隨機訪問,使用ListIteratorListIterator 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);}}
}
源碼解讀:
- 根據列表大小和是否實現 RandomAccess 接口選擇不同的實現策略
- 小列表或者隨機訪問列表采用直接索引交換的方式
- 大列表且非隨機訪問采用 LIstIterator
示例:
import java.util.*;public class ReverseExample {public static void main(String[] args) {List<String> colors = new ArrayList<>();Collections.addAll(colors, "red", "green", "blue", "yellow");System.out.println("反轉前: " + colors);// 輸出: 反轉前: [red, green, blue, yellow]Collections.reverse(colors);System.out.println("反轉后: " + colors);// 輸出: 反轉后: [yellow, blue, green, red]}
}
4、shuffle
方法聲明:
????????public static void shuffle(List<?> list)
????????public static void shuffle(List<?> list, Random rnd)
調用者:
? ? ? ? Collections
參數:
? ? ? ? List<?> list:要打亂的集合
? ? ? ? Random rnd:隨機數生成器(可選)? ?
返回值:
? ? ? ? void
作用:
? ? ? ? 隨機打亂列表中的元素順序
是否改變原始值:
? ? ? ? 是,會修改原集合
注意事項:
? ? ? ? 可以傳入自定義的Random對象以控制隨機種子
源碼:
public static void shuffle(List<?> list) {Random rnd = r;if (rnd == null)r = rnd = new Random();shuffle(list, rnd);
}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();for (int i=size; i>1; i--)swap(arr, i-1, rnd.nextInt(i));ListIterator it = list.listIterator();for (int i=0; i<arr.length; i++) {it.next();it.set(arr[i]);}}
}
源碼解讀:
- 使用 Fisher-Yates 洗牌算法實現隨機打亂
- 根據列表大小和是否實現 RandomAccess 接口選擇不同的實現策略
示例:
import java.util.*;public class ShuffleExample {public static void main(String[] args) {List<Integer> cards = new ArrayList<>();for (int i = 1; i <= 10; i++) {cards.add(i);}System.out.println("洗牌前: " + cards);Collections.shuffle(cards);System.out.println("洗牌后: " + cards);// 使用固定種子的隨機數生成器Collections.shuffle(cards, new Random(123));System.out.println("固定種子洗牌: " + cards);}
}
5、max/min
方法聲明:
????????public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)
????????public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
調用者:
? ? ? ? Collections
參數:
? ? ? ? Collection<? extends T> coll:要查找的集合
? ? ? ? Comparator<? super T> comp:比較器(可選)
返回值:
? ? ? ? T,集合中的最大或最小元素
作用:
? ? ? ? 查找集合中的最大或最小元素
是否改變原始值:
? ? ? ? 否,不修改原集合
注意事項:
? ? ? ? 自然排序要求實現 Comparable 接口
? ? ? ? 空集合會拋出 NoSuchElementException
源碼:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {Iterator<? extends T> i = coll.iterator();T candidate = i.next();while (i.hasNext()) {T next = i.next();if (next.compareTo(candidate) < 0)candidate = next;}return candidate;
}public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {if (comp==null)return (T)min((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;
}
源碼解讀:
- 通過迭代器遍歷集合,比較元素大小
- 自然排序使用 compareTo 方法,比較器排序使用 compare 方法
示例:
import java.util.*;public class MaxMinExample {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();Collections.addAll(numbers, 10, 5, 8, 3, 15, 7);Integer max = Collections.max(numbers);Integer min = Collections.min(numbers);System.out.println("數字列表: " + numbers);System.out.println("最大值: " + max); // 輸出: 最大值: 15System.out.println("最小值: " + min); // 輸出: 最小值: 3// 使用自定義比較器(按絕對值比較)List<Integer> negativeNumbers = new ArrayList<>();Collections.addAll(negativeNumbers, -10, 5, -8, 3);// 按絕對值找最大值Integer maxAbs = Collections.max(negativeNumbers, Comparator.comparing(Math::abs));System.out.println("絕對值最大: " + maxAbs); // 輸出: 絕對值最大: -10}
}
6、fill
方法聲明:
????????public static <T> void fill(List<? super T> list, T obj)
調用者:
? ? ? ? Collections
參數:
? ? ? ? List<? super T> list:要填充的集合
? ? ? ? T obj:用于填充的對象
返回值:
? ? ? ? void
作用:
? ? ? ? 使用指定的元素替換集合中的所有元素
是否改變原始值:
? ? ? ? 是,會修改原集合
注意事項:
? ? ? ? 集合必須已經有元素,不能是空列表
源碼:
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);}}
}
源碼解讀:
- 根據列表大小和是否實現 RandomAccess 接口選擇不同的實現策略
- 使用索引或迭代器將所有元素替換為指定對象
示例:
import java.util.*;public class FillExample {public static void main(String[] args) {List<String> list = new ArrayList<>(Arrays.asList(new String[5]));System.out.println("填充前: " + list);Collections.fill(list, "default");System.out.println("填充后: " + list);// 輸出: 填充后: [default, default, default, default, default]// 也可以用于初始化List<Integer> numbers = new ArrayList<>(Collections.nCopies(5, 0));System.out.println("初始化: " + numbers);Collections.fill(numbers, 1);System.out.println("填充為1: " + numbers);}
}
7、binarySearch
方法聲明:
????????public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
????????private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
調用者:
? ? ? ? Collections
參數:
? ? ? ? List<? extends Comparable<? super T>> list:已降序的集合
? ? ? ? T key:要查找的鍵
? ? ? ? Comparator<? super T> c:比較器(可選)?
返回值:
? ? ? ? int,找到則返回索引,未找到則返回負數
作用:
? ? ? ? 在已排序集合中查找指定元素
是否改變原始值:
? ? ? ? 否,不修改原集合
注意事項:
? ? ? ? 集合必須已經排序
? ? ? ? 返回值為負數時表示未找到,其絕對值減 1 是應該插入的位置
源碼:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)return Collections.indexedBinarySearch(list, key);elsereturn Collections.iteratorBinarySearch(list, key);
}private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {int low = 0;int high = list.size()-1;while (low <= high) {int mid = (low + high) >>> 1;Comparable<? super T> midVal = list.get(mid);int cmp = midVal.compareTo(key);if (cmp < 0)low = mid + 1;else if (cmp > 0)high = mid - 1;elsereturn mid; // key found}return -(low + 1); // key not found
}
源碼解讀:
- 實現標準的二分查找算法
- 根據列表是否實現 RandomAccess 接口選擇不同的實現策略
示例:
import java.util.*;public class BinarySearchExample {public static void main(String[] args) {List<Integer> sortedList = new ArrayList<>();Collections.addAll(sortedList, 1, 3, 5, 7, 9, 11, 13);int index = Collections.binarySearch(sortedList, 7);System.out.println("元素7的索引: " + index); // 輸出: 元素7的索引: 3int notFoundIndex = Collections.binarySearch(sortedList, 6);System.out.println("元素6的索引: " + notFoundIndex); // 輸出: 元素6的索引: -4System.out.println("應該插入的位置: " + (Math.abs(notFoundIndex) - 1)); // 輸出: 應該插入的位置: 3}
}