在 Java 開發中,集合類幾乎貫穿每一個項目,而Collections工具類提供了一系列強大的方法,用于操作和增強集合的功能。無論是排序、查找還是線程安全的封裝,Collections工具類都是提升代碼效率和質量的重要工具。
一、Collections 工具類概述
java.util.Collections是 Java 提供的一個工具類,主要用于操作集合類(如 List、Set 和 Map)。其核心方法包括:
1.排序操作:如sort()和reverseOrder()。
2.查找與填充:如binarySearch()和fill()。
3.其他操作:如shuffle()、swap()等。
4.線程安全包裝:如synchronizedList()和synchronizedMap()。
5.不可變集合:如unmodifiableList()。
二、排序操作:讓數據更有序
Collections.sort()是最常用的方法之一,可對 List 進行自然排序或自定義排序。
示例 1:自然排序
import java.util.*;public class CollectionsSortExample {public static void main(String[] args) {List<String> list = new ArrayList<>(Arrays.asList("banana", "apple", "cherry"));// 自然排序Collections.sort(list);System.out.println("自然排序后: " + list); // 輸出: [apple, banana, cherry]}
}
示例 2:自定義排序
Collections.sort(list, Comparator.reverseOrder());
System.out.println("降序排序后: " + list); // 輸出: [cherry, banana, apple]
實戰場景:商品價格排序
假設有一個商品列表,需要按價格從低到高排序:
List<Product> products = Arrays.asList(new Product("Apple", 100),new Product("Banana", 60),new Product("Cherry", 120)
);Collections.sort(products, Comparator.comparingInt(Product::getPrice));
System.out.println("按價格排序后的商品: " + products);
三、查找與填充
1. Collections.binarySearch()
binarySearch()用于在排序后的列表中快速查找元素的位置。
import java.util.*;public class CollectionsBinarySearchExample {public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 3, 5, 7, 9);// 必須先排序Collections.sort(list);int index = Collections.binarySearch(list, 5);System.out.println("元素 5 的索引位置: " + index); // 輸出: 2}
}
注意:
binarySearch()的前提是列表必須是有序的,否則結果不可預測。
2. Collections.fill()
fill()可將集合中的所有元素替換為指定值。
import java.util.*;
public class CollectionsFillExample {public static void main(String[] args) {List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));Collections.fill(list, "X");System.out.println("填充后的集合: " + list); // 輸出: [X, X, X]}
}
四、其他操作
1. Collections.shuffle()
shuffle()用于將集合中的元素隨機排列,適合打亂順序的場景,如洗牌程序或抽獎工具。
Collections.shuffle(list);
System.out.println("打亂順序后的集合: " + list);
實戰場景:洗牌功能實現
List<String> deck = new ArrayList<>(Arrays.asList("?A", "?2", "?3", "?A", "?2", "?3"
));
Collections.shuffle(deck);
System.out.println("洗牌后的結果: " + deck);
2. Collections.swap()
swap()方法可交換集合中兩個元素的位置。
import java.util.*;public class SwapExample {public static void main(String[] args) {List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));Collections.swap(list, 0, 2);System.out.println("交換后的列表: " + list); // 輸出: [C, B, A]}
}
實戰場景:數組中最小值和最大值交換
List<Integer> list = Arrays.asList(3, 5, 1, 9, 7);
int minIndex = list.indexOf(Collections.min(list));
int maxIndex = list.indexOf(Collections.max(list));
Collections.swap(list, minIndex, maxIndex);
System.out.println("交換后: " + list); // 示例輸出: [9, 5, 1, 3, 7]
五、線程安全包裝
在多線程環境中,原生集合類如ArrayList并不是線程安全的,可以通過Collections.synchronizedXXX()方法生成線程安全的集合。
示例 1:線程安全的集合包裝
import java.util.*;public class SynchronizedCollectionsExample {public static void main(String[] args) {List<String> list = new ArrayList<>();// 轉換為線程安全的 ListList<String> synchronizedList = Collections.synchronizedList(list);synchronizedList.add("Thread-safe");System.out.println("線程安全的集合: " + synchronizedList);}
}
實戰場景:多線程統計數據
List<Integer> scores = Collections.synchronizedList(new ArrayList<>());Runnable task = () -> {for (int i = 0; i < 1000; i++) {scores.add(i);}
};Thread t1 = new Thread(task);
Thread t2 = new Thread(task);t1.start();
t2.start();try {t1.join();t2.join();
} catch (InterruptedException e) {e.printStackTrace();
}System.out.println("線程安全的集合大小: " + scores.size());
六、不可變集合:安全共享數據
不可變集合是指在創建后無法修改的集合類型,適合在多線程環境下共享數據。
示例 1: 創建不可變集合
unmodifiableList
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(list);// 嘗試修改會拋出 UnsupportedOperationException
try {unmodifiableList.add("D");
} catch (UnsupportedOperationException e) {System.out.println("Cannot modify immutable list!");
}
實戰場景:配置文件的共享
Map<String, String> config = new HashMap<>();
config.put("host", "localhost");
config.put("port", "8080");Map<String, String> unmodifiableConfig = Collections.unmodifiableMap(config);// 多個線程可以安全地讀取配置
Runnable task = () -> {System.out.println("Host: " + unmodifiableConfig.get("host"));
};Thread t1 = new Thread(task);
Thread t2 = new Thread(task);t1.start();
t2.start();
七、性能優化建議
1.避免頻繁排序
對于動態數據的排序,建議使用TreeSet或PriorityQueue。
2.選擇合適的線程安全集合
在頻繁讀寫場景中,優先考慮ConcurrentHash-Map或CopyOnWriteArrayList。
3.減少鎖競爭
使用synchronizedList時,盡量避免在循環中頻繁調用修改操作。
八、綜合實戰:線程安全排行榜
以下案例展示如何結合Collections工具類創建線程安全的排行榜:
import java.util.*;public class LeaderboardExample {public static void main(String[] args) {// 創建線程安全的排行榜(List)List<Integer> scores = Collections.synchronizedList(new ArrayList<>());// 添加分數scores.addAll(Arrays.asList(85, 90, 75, 95, 88));// 排序Collections.sort(scores, Collections.reverseOrder());System.out.println("排行榜: " + scores); // 輸出: [95, 90, 88, 85, 75]// 查找某個分數的排名int rank = Collections.binarySearch(scores, 90, Collections.reverseOrder());System.out.println("分數 90 的排名: 第 " + (rank + 1) + " 名");}
}