📋 目录
🚀 框架概述
Java集合框架(Java Collections Framework)是Java核心API的重要组成部分,提供了一套标准的、高效的数据结构和算法实现。框架采用统一的架构设计,通过接口和实现类的分离,为开发者提供了灵活、可扩展的容器解决方案。
框架结构图
核心特性
- 统一接口设计:通过继承体系提供一致的API
- 泛型支持:类型安全,减少强制转换
- 自动扩容:动态调整容量,适应数据量变化
- 丰富的算法:内置排序、搜索、洗牌等实用算法
- 性能优化:针对不同使用场景的专门实现
📚 Collection单列集合详解
List接口:有序可重复集合
ArrayList - 动态数组实现
核心特征:
- 基于可变数组实现
- 支持随机访问(索引访问)
- 线程不安全
- 默认初始容量为10
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
// 创建ArrayList
List<String> list = new ArrayList<>();
// 添加元素
list.add("Java");
list.add("Python");
list.add("JavaScript");
list.add("Java"); // 允许重复
// 指定位置插入
list.add(1, "C++");
// 访问元素
System.out.println("第一个元素: " + list.get(0));
System.out.println("列表大小: " + list.size());
// 查找元素
int index = list.indexOf("Java");
System.out.println("Java的位置: " + index);
// 修改元素
list.set(0, "Kotlin");
// 删除元素
list.remove("Python");
list.remove(0); // 按索引删除
System.out.println("最终列表: " + list);
// 批量操作
List<String> newElements = Arrays.asList("Go", "Rust");
list.addAll(newElements);
// 转换为数组
String[] array = list.toArray(new String[0]);
System.out.println("转换为数组: " + Arrays.toString(array));
}
}
LinkedList - 双向链表实现
核心特征:
- 基于双向链表实现
- 插入删除效率高
- 不支持随机访问
- 实现了List和Deque接口
import java.util.*;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
// 队列操作
list.addFirst(1);
list.addLast(3);
list.add(1, 2); // 在索引1处插入
System.out.println("链表内容: " + list);
// 栈操作
list.push(0); // 压栈
System.out.println("压栈后: " + list);
int popped = list.pop(); // 出栈
System.out.println("出栈元素: " + popped);
// 队列操作
list.offer(4); // 入队
int head = list.poll(); // 出队
System.out.println("出队元素: " + head);
// 获取首尾元素
System.out.println("首元素: " + list.peekFirst());
System.out.println("尾元素: " + list.peekLast());
// 性能测试:频繁插入删除
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
list.add(0, i); // 在头部插入
}
long endTime = System.currentTimeMillis();
System.out.println("LinkedList头部插入耗时: " + (endTime - startTime) + "ms");
}
}
Set接口:无序不重复集合
HashSet - 哈希表实现
import java.util.*;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Cherry");
set.add("Apple"); // 重复元素,不会被添加
System.out.println("Set大小: " + set.size());
System.out.println("Set内容: " + set);
// 检查元素存在
if (set.contains("Apple")) {
System.out.println("包含Apple");
}
// 集合运算
Set<String> otherSet = new HashSet<>(Arrays.asList("Banana", "Date", "Elderberry"));
// 交集
Set<String> intersection = new HashSet<>(set);
intersection.retainAll(otherSet);
System.out.println("交集: " + intersection);
// 并集
Set<String> union = new HashSet<>(set);
union.addAll(otherSet);
System.out.println("并集: " + union);
// 差集
Set<String> difference = new HashSet<>(set);
difference.removeAll(otherSet);
System.out.println("差集: " + difference);
}
}
TreeSet - 红黑树实现
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
// 自然排序
TreeSet<Integer> numbers = new TreeSet<>();
numbers.addAll(Arrays.asList(5, 2, 8, 1, 9, 3));
System.out.println("自然排序: " + numbers);
// 自定义排序
TreeSet<String> words = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
words.addAll(Arrays.asList("apple", "Banana", "cherry", "Date"));
System.out.println("忽略大小写排序: " + words);
// 范围操作
TreeSet<Integer> scores = new TreeSet<>(Arrays.asList(85, 92, 78, 96, 88, 73, 91));
// 获取子集
System.out.println("80分以上: " + scores.tailSet(80));
System.out.println("90分以下: " + scores.headSet(90));
System.out.println("80-90分: " + scores.subSet(80, 90));
// 获取边界值
System.out.println("最高分: " + scores.last());
System.out.println("最低分: " + scores.first());
System.out.println("小于90的最高分: " + scores.lower(90));
System.out.println("大于80的最低分: " + scores.higher(80));
}
}
Queue接口:队列集合
PriorityQueue - 优先队列
import java.util.*;
public class PriorityQueueDemo {
public static void main(String[] args) {
// 最小堆(默认)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.addAll(Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6));
System.out.println("最小堆出队顺序:");
while (!minHeap.isEmpty()) {
System.out.print(minHeap.poll() + " ");
}
System.out.println();
// 最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
maxHeap.addAll(Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6));
System.out.println("最大堆出队顺序:");
while (!maxHeap.isEmpty()) {
System.out.print(maxHeap.poll() + " ");
}
System.out.println();
// 自定义优先级:任务调度示例
PriorityQueue<Task> taskQueue = new PriorityQueue<>();
taskQueue.offer(new Task("低优先级任务", 3));
taskQueue.offer(new Task("高优先级任务", 1));
taskQueue.offer(new Task("中优先级任务", 2));
System.out.println("任务执行顺序:");
while (!taskQueue.isEmpty()) {
System.out.println(taskQueue.poll());
}
}
static class Task implements Comparable<Task> {
String name;
int priority;
Task(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public int compareTo(Task other) {
return Integer.compare(this.priority, other.priority);
}
@Override
public String toString() {
return name + " (优先级: " + priority + ")";
}
}
}
🗺️ Map双列集合详解
HashMap - 哈希表实现
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("Java", 25);
map.put("Python", 30);
map.put("JavaScript", 28);
map.put("C++", 35);
// 获取值
Integer javaAge = map.get("Java");
System.out.println("Java年龄: " + javaAge);
// 安全获取(避免null)
Integer kotlinAge = map.getOrDefault("Kotlin", 0);
System.out.println("Kotlin年龄: " + kotlinAge);
// 条件更新
map.putIfAbsent("Go", 12); // 键不存在时才插入
map.computeIfPresent("Java", (k, v) -> v + 1); // 键存在时计算新值
map.computeIfAbsent("Rust", k -> 6); // 键不存在时计算值
// 遍历方法对比
System.out.println("\n=== 遍历方法对比 ===");
// 方法1:遍历entrySet(推荐)
System.out.println("方法1 - entrySet:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
// 方法2:Lambda表达式(推荐)
System.out.println("\n方法2 - forEach:");
map.forEach((key, value) -> System.out.println(key + " -> " + value));
// 方法3:分别遍历键和值(不推荐,效率低)
System.out.println("\n方法3 - keySet:");
for (String key : map.keySet()) {
System.out.println(key + " -> " + map.get(key));
}
}
}
TreeMap - 红黑树实现
import java.util.*;
public class TreeMapDemo {
public static void main(String[] args) {
// 自然排序的TreeMap
TreeMap<String, Double> scores = new TreeMap<>();
scores.put("Alice", 95.5);
scores.put("Bob", 87.2);
scores.put("Charlie", 92.8);
scores.put("David", 78.9);
System.out.println("按姓名排序: " + scores);
// 按值排序的TreeMap
TreeMap<String, Double> scoresByValue = new TreeMap<>((k1, k2) -> {
return scores.get(k2).compareTo(scores.get(k1)); // 降序
});
scoresByValue.putAll(scores);
// 范围查询
System.out.println("B-D之间的学生: " + scores.subMap("B", "E"));
System.out.println("最高分学生: " + scores.lastEntry());
System.out.println("最低分学生: " + scores.firstEntry());
// 导航方法
System.out.println("Charlie之前的学生: " + scores.lowerEntry("Charlie"));
System.out.println("David之后的学生: " + scores.higherEntry("David"));
}
}
⚡ 集合性能对比分析
时间复杂度对比表
操作 | ArrayList | LinkedList | HashSet | TreeSet | HashMap | TreeMap |
---|---|---|---|---|---|---|
添加 | O(1)* | O(1) | O(1)* | O(log n) | O(1)* | O(log n) |
删除 | O(n) | O(1)** | O(1)* | O(log n) | O(1)* | O(log n) |
查找 | O(1) | O(n) | O(1)* | O(log n) | O(1)* | O(log n) |
遍历 | O(n) | O(n) | O(n) | O(n) | O(n) | O(n) |
*平均情况下,最坏情况可能是O(n)
**已知节点位置的情况下
性能测试实例
import java.util.*;
public class PerformanceTest {
private static final int TEST_SIZE = 100000;
public static void main(String[] args) {
testListPerformance();
testSetPerformance();
testMapPerformance();
}
private static void testListPerformance() {
System.out.println("=== List性能测试 ===");
// ArrayList vs LinkedList 插入性能
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
// 尾部插入测试
long startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
arrayList.add(i);
}
System.out.println("ArrayList尾部插入: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
linkedList.add(i);
}
System.out.println("LinkedList尾部插入: " + (System.currentTimeMillis() - startTime) + "ms");
// 头部插入测试
arrayList.clear();
linkedList.clear();
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) { // 减少测试量,ArrayList头部插入很慢
arrayList.add(0, i);
}
System.out.println("ArrayList头部插入: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
linkedList.add(0, i);
}
System.out.println("LinkedList头部插入: " + (System.currentTimeMillis() - startTime) + "ms");
}
private static void testSetPerformance() {
System.out.println("\n=== Set性能测试 ===");
Set<Integer> hashSet = new HashSet<>();
Set<Integer> treeSet = new TreeSet<>();
// 添加性能测试
long startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
hashSet.add(i);
}
System.out.println("HashSet添加: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
treeSet.add(i);
}
System.out.println("TreeSet添加: " + (System.currentTimeMillis() - startTime) + "ms");
// 查找性能测试
Random random = new Random();
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
hashSet.contains(random.nextInt(TEST_SIZE));
}
System.out.println("HashSet查找: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
treeSet.contains(random.nextInt(TEST_SIZE));
}
System.out.println("TreeSet查找: " + (System.currentTimeMillis() - startTime) + "ms");
}
private static void testMapPerformance() {
System.out.println("\n=== Map性能测试 ===");
Map<Integer, String> hashMap = new HashMap<>();
Map<Integer, String> treeMap = new TreeMap<>();
// 插入性能测试
long startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
hashMap.put(i, "Value" + i);
}
System.out.println("HashMap插入: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_SIZE; i++) {
treeMap.put(i, "Value" + i);
}
System.out.println("TreeMap插入: " + (System.currentTimeMillis() - startTime) + "ms");
}
}
🔒 并发集合与线程安全
传统同步方式
import java.util.*;
import java.util.concurrent.*;
public class ThreadSafeCollections {
public static void main(String[] args) {
// 使用Collections.synchronizedXxx
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
// 使用Vector和Hashtable(不推荐)
Vector<String> vector = new Vector<>();
Hashtable<String, Integer> hashtable = new Hashtable<>();
testConcurrentAccess(syncList, "SynchronizedList");
}
private static void testConcurrentAccess(List<String> list, String type) {
ExecutorService executor = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
final int threadId = i;
executor.submit(() -> {
try {
for (int j = 0; j < 1000; j++) {
list.add("Thread" + threadId + "-Item" + j);
}
} finally {
latch.countDown();
}
});
}
try {
latch.await();
System.out.println(type + " 最终大小: " + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
现代并发集合
import java.util.concurrent.*;
import java.util.*;
public class ModernConcurrentCollections {
public static void main(String[] args) throws InterruptedException {
demonstrateConcurrentHashMap();
demonstrateCopyOnWriteArrayList();
demonstrateBlockingQueue();
}
private static void demonstrateConcurrentHashMap() {
System.out.println("=== ConcurrentHashMap演示 ===");
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 原子操作
map.put("counter", 0);
// 多线程安全的计算操作
ExecutorService executor = Executors.newFixedThreadPool(5);
CountDownLatch latch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
try {
for (int j = 0; j < 1000; j++) {
map.compute("counter", (k, v) -> v == null ? 1 : v + 1);
}
} finally {
latch.countDown();
}
});
}
try {
latch.await();
System.out.println("最终计数: " + map.get("counter"));
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
}
private static void demonstrateCopyOnWriteArrayList() {
System.out.println("\n=== CopyOnWriteArrayList演示 ===");
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.addAll(Arrays.asList("A", "B", "C"));
// 读操作不加锁,写操作复制整个数组
ExecutorService executor = Executors.newFixedThreadPool(10);
// 读线程
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
for (int j = 0; j < 100; j++) {
for (String item : list) {
// 读操作,即使在写操作进行时也不会抛出ConcurrentModificationException
}
}
});
}
// 写线程
for (int i = 0; i < 5; i++) {
final int threadId = i;
executor.submit(() -> {
for (int j = 0; j < 10; j++) {
list.add("Item-" + threadId + "-" + j);
}
});
}
executor.shutdown();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
System.out.println("CopyOnWriteArrayList最终大小: " + list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void demonstrateBlockingQueue() {
System.out.println("\n=== BlockingQueue演示 ===");
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
queue.put("Product-" + i);
System.out.println("生产: Product-" + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 消费者
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 20; i++) {
String product = queue.take();
System.out.println("消费: " + product);
Thread.sleep(150);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
🔄 集合遍历与迭代器
迭代器详解
import java.util.*;
public class IteratorDemo {
public static void main(String[] args) {
demonstrateIterator();
demonstrateListIterator();
demonstrateFail_Fast_Fail_Safe();
}
private static void demonstrateIterator() {
System.out.println("=== Iterator演示 ===");
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
// 基本迭代
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if ("C".equals(item)) {
it.remove(); // 安全删除
}
}
System.out.println("删除C后: " + list);
// 增强for循环(语法糖)
for (String item : list) {
System.out.print(item + " ");
}
System.out.println();
}
private static void demonstrateListIterator() {
System.out.println("\n=== ListIterator演示 ===");
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ListIterator<Integer> listIt = list.listIterator();
// 正向遍历并修改
while (listIt.hasNext()) {
int value = listIt.next();
if (value % 2 == 0) {
listIt.set(value * 10); // 修改当前元素
}
if (value == 3) {
listIt.add(35); // 在当前位置后插入
}
}
System.out.println("修改后: " + list);
// 反向遍历
System.out.print("反向遍历: ");
while (listIt.hasPrevious()) {
System.out.print(listIt.previous() + " ");
}
System.out.println();
}
private static void demonstrateFail_Fast_Fail_Safe() {
System.out.println("\n=== Fail-Fast vs Fail-Safe演示 ===");
// Fail-Fast示例(ArrayList)
List<String> failFastList = new ArrayList<>(Arrays.asList("A", "B", "C"));
try {
for (String item : failFastList) {
if ("B".equals(item)) {
failFastList.remove(item); // 会抛出ConcurrentModificationException
}
}
} catch (ConcurrentModificationException e) {
System.out.println("捕获到ConcurrentModificationException: " + e.getMessage());
}
// Fail-Safe示例(CopyOnWriteArrayList)
List<String> failSafeList = new CopyOnWriteArrayList<>(Arrays.asList("A", "B", "C"));
for (String item : failSafeList) {
if ("B".equals(item)) {
failSafeList.remove(item); // 不会抛出异常,但可能看不到修改
}
}
System.out.println("Fail-Safe列表: " + failSafeList);
}
}
🔧 常用API详解
Collections工具类
Collections类提供了大量静态方法来操作集合,是日常开发中最常用的工具类之一。
import java.util.*;
public class CollectionsAPIDemo {
public static void main(String[] args) {
demonstrateBasicOperations();
demonstrateSortingAndSearching();
demonstrateSynchronization();
demonstrateImmutableCollections();
}
private static void demonstrateBasicOperations() {
System.out.println("=== Collections基本操作 ===");
List<String> list = new ArrayList<>(Arrays.asList("C", "A", "B", "D"));
System.out.println("原始列表: " + list);
// 排序
Collections.sort(list);
System.out.println("排序后: " + list);
// 反转
Collections.reverse(list);
System.out.println("反转后: " + list);
// 洗牌
Collections.shuffle(list);
System.out.println("洗牌后: " + list);
// 填充
Collections.fill(list, "X");
System.out.println("填充后: " + list);
// 复制
List<String> source = Arrays.asList("1", "2", "3", "4");
List<String> dest = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
Collections.copy(dest, source);
System.out.println("复制后: " + dest);
// 替换
List<String> replaceList = new ArrayList<>(Arrays.asList("A", "B", "A", "C"));
Collections.replaceAll(replaceList, "A", "X");
System.out.println("替换后: " + replaceList);
// 频率统计
List<String> frequencyList = Arrays.asList("A", "B", "A", "C", "A", "B");
int frequency = Collections.frequency(frequencyList, "A");
System.out.println("A出现次数: " + frequency);
// 最大最小值
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
System.out.println("最大值: " + Collections.max(numbers));
System.out.println("最小值: " + Collections.min(numbers));
}
private static void demonstrateSortingAndSearching() {
System.out.println("\n=== 排序和搜索 ===");
List<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date"));
// 自定义排序
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
System.out.println("忽略大小写排序: " + list);
// 自定义比较器排序
Collections.sort(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
System.out.println("按长度排序: " + list);
// 二分查找(需要先排序)
Collections.sort(list);
int index = Collections.binarySearch(list, "Cherry");
System.out.println("Cherry的位置: " + index);
// 如果元素不存在,返回负数
int notFound = Collections.binarySearch(list, "Elderberry");
System.out.println("Elderberry的位置: " + notFound + " (负数表示不存在)");
}
private static void demonstrateSynchronization() {
System.out.println("\n=== 同步包装器 ===");
// 创建同步集合
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());
// 同步集合的遍历需要手动同步
syncList.addAll(Arrays.asList("A", "B", "C"));
synchronized (syncList) {
Iterator<String> it = syncList.iterator();
while (it.hasNext()) {
System.out.println("同步列表元素: " + it.next());
}
}
}
private static void demonstrateImmutableCollections() {
System.out.println("\n=== 不可变集合 ===");
// 空集合
List<String> emptyList = Collections.emptyList();
Set<String> emptySet = Collections.emptySet();
Map<String, String> emptyMap = Collections.emptyMap();
// 单元素集合
List<String> singletonList = Collections.singletonList("OnlyOne");
Set<String> singletonSet = Collections.singleton("OnlyOne");
Map<String, String> singletonMap = Collections.singletonMap("key", "value");
System.out.println("单元素列表: " + singletonList);
System.out.println("单元素集合: " + singletonSet);
System.out.println("单元素映射: " + singletonMap);
// 不可修改的集合
List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);
try {
unmodifiableList.add("D"); // 会抛出异常
} catch (UnsupportedOperationException e) {
System.out.println("不可修改集合抛出异常: " + e.getClass().getSimpleName());
}
// 原始列表修改会影响不可修改视图
mutableList.add("D");
System.out.println("原始列表修改后的不可修改视图: " + unmodifiableList);
}
}
Arrays工具类
Arrays类提供了操作数组的各种静态方法,与集合操作密切相关。
import java.util.*;
public class ArraysAPIDemo {
public static void main(String[] args) {
demonstrateBasicOperations();
demonstrateConversions();
demonstrateComparisons();
}
private static void demonstrateBasicOperations() {
System.out.println("=== Arrays基本操作 ===");
int[] numbers = {3, 1, 4, 1, 5, 9, 2, 6};
System.out.println("原始数组: " + Arrays.toString(numbers));
// 排序
Arrays.sort(numbers);
System.out.println("排序后: " + Arrays.toString(numbers));
// 二分查找
int index = Arrays.binarySearch(numbers, 4);
System.out.println("数字4的位置: " + index);
// 填充
int[] fillArray = new int[5];
Arrays.fill(fillArray, 42);
System.out.println("填充数组: " + Arrays.toString(fillArray));
// 部分填充
int[] partialFillArray = new int[10];
Arrays.fill(partialFillArray, 2, 8, 99);
System.out.println("部分填充: " + Arrays.toString(partialFillArray));
// 复制数组
int[] copied = Arrays.copyOf(numbers, numbers.length);
System.out.println("复制数组: " + Arrays.toString(copied));
// 复制部分数组
int[] partialCopy = Arrays.copyOfRange(numbers, 2, 6);
System.out.println("部分复制: " + Arrays.toString(partialCopy));
}
private static void demonstrateConversions() {
System.out.println("\n=== 数组与集合转换 ===");
// 数组转List
String[] array = {"A", "B", "C", "D"};
List<String> list = Arrays.asList(array);
System.out.println("数组转List: " + list);
// 注意:Arrays.asList返回的是固定大小的列表
try {
list.add("E"); // 会抛出异常
} catch (UnsupportedOperationException e) {
System.out.println("固定大小列表不能添加元素");
}
// 创建可变列表
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
mutableList.add("E");
System.out.println("可变列表: " + mutableList);
// List转数组
String[] backToArray = mutableList.toArray(new String[0]);
System.out.println("List转数组: " + Arrays.toString(backToArray));
// 基本类型数组的处理
int[] intArray = {1, 2, 3, 4, 5};
// 基本类型不能直接用Arrays.asList
List<Integer> intList = new ArrayList<>();
for (int i : intArray) {
intList.add(i);
}
System.out.println("基本类型转List: " + intList);
// Java 8+ 方式
List<Integer> streamList = Arrays.stream(intArray)
.boxed()
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println("Stream方式转换: " + streamList);
}
private static void demonstrateComparisons() {
System.out.println("\n=== 数组比较 ===");
int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = {1, 2, 3, 4, 5};
int[] array3 = {1, 2, 3, 4, 6};
// 数组相等比较
System.out.println("array1 == array2: " + (array1 == array2)); // false
System.out.println("Arrays.equals(array1, array2): " + Arrays.equals(array1, array2)); // true
System.out.println("Arrays.equals(array1, array3): " + Arrays.equals(array1, array3)); // false
// 数组比较
System.out.println("Arrays.compare(array1, array3): " + Arrays.compare(array1, array3));
// 二维数组比较
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{1, 2}, {3, 4}};
System.out.println("深度相等: " + Arrays.deepEquals(matrix1, matrix2));
System.out.println("二维数组toString: " + Arrays.deepToString(matrix1));
}
}
Stream API常用操作
Java 8引入的Stream API为集合操作提供了函数式编程的方式。
import java.util.*;
import java.util.stream.*;
public class StreamAPIDemo {
public static void main(String[] args) {
demonstrateBasicOperations();
demonstrateFilteringAndMapping();
demonstrateReductionOperations();
demonstrateCollectors();
demonstrateAdvancedOperations();
}
private static void demonstrateBasicOperations() {
System.out.println("=== Stream基本操作 ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 创建Stream
Stream<Integer> stream = numbers.stream();
// 遍历
System.out.print("forEach遍历: ");
numbers.stream().forEach(n -> System.out.print(n + " "));
System.out.println();
// 计数
long count = numbers.stream().count();
System.out.println("元素个数: " + count);
// 查找
Optional<Integer> first = numbers.stream().findFirst();
System.out.println("第一个元素: " + first.orElse(-1));
Optional<Integer> any = numbers.stream().findAny();
System.out.println("任意元素: " + any.orElse(-1));
// 匹配
boolean allPositive = numbers.stream().allMatch(n -> n > 0);
boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
System.out.println("全部为正数: " + allPositive);
System.out.println("包含偶数: " + anyEven);
System.out.println("没有负数: " + noneNegative);
}
private static void demonstrateFilteringAndMapping() {
System.out.println("\n=== 过滤和映射 ===");
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
// 过滤
List<String> longWords = words.stream()
.filter(word -> word.length() > 5)
.collect(Collectors.toList());
System.out.println("长度大于5的单词: " + longWords);
// 映射
List<Integer> lengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println("单词长度: " + lengths);
// 转大写
List<String> upperWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("转大写: " + upperWords);
// 扁平化映射
List<String> sentences = Arrays.asList("Hello World", "Java Stream", "API Demo");
List<String> allWords = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split(" ")))
.collect(Collectors.toList());
System.out.println("所有单词: " + allWords);
// 去重
List<String> distinctWords = Arrays.asList("a", "b", "a", "c", "b", "d")
.stream()
.distinct()
.collect(Collectors.toList());
System.out.println("去重后: " + distinctWords);
// 排序
List<String> sortedWords = words.stream()
.sorted()
.collect(Collectors.toList());
System.out.println("排序后: " + sortedWords);
// 限制和跳过
List<String> limitedWords = words.stream()
.skip(1)
.limit(3)
.collect(Collectors.toList());
System.out.println("跳过1个,取3个: " + limitedWords);
}
private static void demonstrateReductionOperations() {
System.out.println("\n=== 归约操作 ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 求和
int sum = numbers.stream().mapToInt(Integer::intValue).sum();
System.out.println("求和: " + sum);
// 最大最小值
OptionalInt max = numbers.stream().mapToInt(Integer::intValue).max();
OptionalInt min = numbers.stream().mapToInt(Integer::intValue).min();
System.out.println("最大值: " + max.orElse(0));
System.out.println("最小值: " + min.orElse(0));
// 平均值
OptionalDouble average = numbers.stream().mapToInt(Integer::intValue).average();
System.out.println("平均值: " + average.orElse(0));
// 统计信息
IntSummaryStatistics stats = numbers.stream()
.mapToInt(Integer::intValue)
.summaryStatistics();
System.out.println("统计信息: " + stats);
// 自定义归约
Optional<Integer> product = numbers.stream()
.reduce((a, b) -> a * b);
System.out.println("乘积: " + product.orElse(0));
// 字符串连接
String joined = Arrays.asList("A", "B", "C", "D")
.stream()
.reduce("", (a, b) -> a + b);
System.out.println("字符串连接: " + joined);
}
private static void demonstrateCollectors() {
System.out.println("\n=== 收集器 ===");
List<Person> people = Arrays.asList(
new Person("Alice", 25, "Engineering"),
new Person("Bob", 30, "Marketing"),
new Person("Charlie", 35, "Engineering"),
new Person("David", 28, "Sales"),
new Person("Eve", 32, "Marketing")
);
// 转换为List
List<String> names = people.stream()
.map(Person::getName)
.collect(Collectors.toList());
System.out.println("姓名列表: " + names);
// 转换为Set
Set<String> departments = people.stream()
.map(Person::getDepartment)
.collect(Collectors.toSet());
System.out.println("部门集合: " + departments);
// 分组
Map<String, List<Person>> byDepartment = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment));
System.out.println("按部门分组: " + byDepartment);
// 分组并计数
Map<String, Long> departmentCounts = people.stream()
.collect(Collectors.groupingBy(Person::getDepartment, Collectors.counting()));
System.out.println("部门人数: " + departmentCounts);
// 分组并获取平均年龄
Map<String, Double> avgAgeByDept = people.stream()
.collect(Collectors.groupingBy(
Person::getDepartment,
Collectors.averagingInt(Person::getAge)
));
System.out.println("部门平均年龄: " + avgAgeByDept);
// 字符串连接
String allNames = people.stream()
.map(Person::getName)
.collect(Collectors.joining(", "));
System.out.println("所有姓名: " + allNames);
// 分区
Map<Boolean, List<Person>> partitioned = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() >= 30));
System.out.println("年龄分区: " + partitioned);
}
private static void demonstrateAdvancedOperations() {
System.out.println("\n=== 高级操作 ===");
// 并行流
List<Integer> numbers = IntStream.rangeClosed(1, 1000)
.boxed()
.collect(Collectors.toList());
long start = System.currentTimeMillis();
long sum1 = numbers.stream()
.mapToLong(Integer::longValue)
.sum();
long time1 = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
long sum2 = numbers.parallelStream()
.mapToLong(Integer::longValue)
.sum();
long time2 = System.currentTimeMillis() - start;
System.out.println("串行流求和: " + sum1 + ", 耗时: " + time1 + "ms");
System.out.println("并行流求和: " + sum2 + ", 耗时: " + time2 + "ms");
// 无限流
List<Integer> randomNumbers = Stream.generate(() -> (int)(Math.random() * 100))
.limit(10)
.collect(Collectors.toList());
System.out.println("随机数: " + randomNumbers);
// 数值范围流
List<Integer> range = IntStream.rangeClosed(1, 10)
.boxed()
.collect(Collectors.toList());
System.out.println("范围流: " + range);
}
static class Person {
private String name;
private int age;
private String department;
public Person(String name, int age, String department) {
this.name = name;
this.age = age;
this.department = department;
}
// getters
public String getName() { return name; }
public int getAge() { return age; }
public String getDepartment() { return department; }
@Override
public String toString() {
return name + "(" + age + ")";
}
}
}
实用工具方法
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CollectionUtils {
/**
* 安全地获取集合的第一个元素
*/
public static <T> Optional<T> getFirst(Collection<T> collection) {
return collection.isEmpty() ? Optional.empty() :
Optional.of(collection.iterator().next());
}
/**
* 安全地获取列表的最后一个元素
*/
public static <T> Optional<T> getLast(List<T> list) {
return list.isEmpty() ? Optional.empty() :
Optional.of(list.get(list.size() - 1));
}
/**
* 判断集合是否为空或null
*/
public static boolean isEmpty(Collection<?> collection) {
return collection == null || collection.isEmpty();
}
/**
* 判断集合是否不为空
*/
public static boolean isNotEmpty(Collection<?> collection) {
return !isEmpty(collection);
}
/**
* 安全地获取集合大小
*/
public static int size(Collection<?> collection) {
return collection == null ? 0 : collection.size();
}
/**
* 创建不可变列表
*/
@SafeVarargs
public static <T> List<T> listOf(T... elements) {
return Collections.unmodifiableList(Arrays.asList(elements));
}
/**
* 创建不可变集合
*/
@SafeVarargs
public static <T> Set<T> setOf(T... elements) {
return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(elements)));
}
/**
* 列表分页
*/
public static <T> List<List<T>> partition(List<T> list, int size) {
if (list == null || size <= 0) {
return Collections.emptyList();
}
List<List<T>> result = new ArrayList<>();
for (int i = 0; i < list.size(); i += size) {
result.add(list.subList(i, Math.min(list.size(), i + size)));
}
return result;
}
/**
* 列表转Map
*/
public static <T, K> Map<K, T> toMap(Collection<T> collection, Function<T, K> keyMapper) {
return collection.stream().collect(Collectors.toMap(keyMapper, Function.identity()));
}
/**
* 列表转Map,处理重复键
*/
public static <T, K, V> Map<K, V> toMap(Collection<T> collection,
Function<T, K> keyMapper,
Function<T, V> valueMapper) {
return collection.stream().collect(
Collectors.toMap(keyMapper, valueMapper, (existing, replacement) -> existing));
}
/**
* 集合差集
*/
public static <T> Set<T> difference(Set<T> set1, Set<T> set2) {
Set<T> result = new HashSet<>(set1);
result.removeAll(set2);
return result;
}
/**
* 集合交集
*/
public static <T> Set<T> intersection(Set<T> set1, Set<T> set2) {
Set<T> result = new HashSet<>(set1);
result.retainAll(set2);
return result;
}
/**
* 集合并集
*/
public static <T> Set<T> union(Set<T> set1, Set<T> set2) {
Set<T> result = new HashSet<>(set1);
result.addAll(set2);
return result;
}
/**
* 列表去重保持顺序
*/
public static <T> List<T> distinct(List<T> list) {
return list.stream().distinct().collect(Collectors.toList());
}
/**
* 安全的集合转换
*/
public static <T> List<T> nullSafeList(List<T> list) {
return list == null ? Collections.emptyList() : list;
}
public static <T> Set<T> nullSafeSet(Set<T> set) {
return set == null ? Collections.emptySet() : set;
}
public static <K, V> Map<K, V> nullSafeMap(Map<K, V> map) {
return map == null ? Collections.emptyMap() : map;
}
// 测试方法
public static void main(String[] args) {
System.out.println("=== 工具方法测试 ===");
List<String> list = Arrays.asList("A", "B", "C", "D", "E");
// 获取第一个和最后一个元素
System.out.println("第一个: " + getFirst(list).orElse("无"));
System.out.println("最后一个: " + getLast(list).orElse("无"));
// 分页测试
List<List<String>> pages = partition(list, 2);
System.out.println("分页结果: " + pages);
// 集合运算测试
Set<Integer> set1 = setOf(1, 2, 3, 4);
Set<Integer> set2 = setOf(3, 4, 5, 6);
System.out.println("差集: " + difference(set1, set2));
System.out.println("交集: " + intersection(set1, set2));
System.out.println("并集: " + union(set1, set2));
// 转Map测试
List<Person> people = Arrays.asList(
new Person("Alice", 25, "IT"),
new Person("Bob", 30, "HR")
);
Map<String, Person> personMap = toMap(people, Person::getName);
System.out.println("人员映射: " + personMap);
}
static class Person {
private String name;
private int age;
private String department;
public Person(String name, int age, String department) {
this.name = name;
this.age = age;
this.department = department;
}
public String getName() { return name; }
public int getAge() { return age; }
public String getDepartment() { return department; }
@Override
public String toString() {
return name + "(" + age + ")";
}
}
}
💡 实战案例与最佳实践
案例1:学生成绩管理系统
import java.util.*;
import java.util.stream.Collectors;
public class StudentGradeManager {
private Map<String, Student> students = new HashMap<>();
private Map<String, List<Double>> subjectGrades = new HashMap<>();
public static void main(String[] args) {
StudentGradeManager manager = new StudentGradeManager();
manager.runDemo();
}
private void runDemo() {
// 添加学生和成绩
addStudent("张三", Arrays.asList(85.5, 92.0, 78.5));
addStudent("李四", Arrays.asList(88.0, 85.5, 91.0));
addStudent("王五", Arrays.asList(92.5, 88.0, 87.5));
// 统计分析
System.out.println("=== 成绩统计分析 ===");
calculateStatistics();
// 排名分析
System.out.println("\n=== 学生排名 ===");
showRanking();
// 科目分析
System.out.println("\n=== 科目分析 ===");
analyzeSubjects();
}
private void addStudent(String name, List<Double> grades) {
Student student = new Student(name, grades);
students.put(name, student);
// 更新科目成绩统计
for (int i = 0; i < grades.size(); i++) {
String subject = "科目" + (i + 1);
subjectGrades.computeIfAbsent(subject, k -> new ArrayList<>()).add(grades.get(i));
}
}
private void calculateStatistics() {
students.values().forEach(student -> {
double average = student.getAverageGrade();
System.out.printf("%s: 平均分 %.2f%n", student.getName(), average);
});
}
private void showRanking() {
List<Student> sortedStudents = students.values().stream()
.sorted((s1, s2) -> Double.compare(s2.getAverageGrade(), s1.getAverageGrade()))
.collect(Collectors.toList());
for (int i = 0; i < sortedStudents.size(); i++) {
Student student = sortedStudents.get(i);
System.out.printf("第%d名: %s (%.2f分)%n",
i + 1, student.getName(), student.getAverageGrade());
}
}
private void analyzeSubjects() {
subjectGrades.forEach((subject, grades) -> {
DoubleSummaryStatistics stats = grades.stream()
.mapToDouble(Double::doubleValue)
.summaryStatistics();
System.out.printf("%s: 平均分 %.2f, 最高分 %.2f, 最低分 %.2f%n",
subject, stats.getAverage(), stats.getMax(), stats.getMin());
});
}
static class Student {
private String name;
private List<Double> grades;
private double averageGrade;
public Student(String name, List<Double> grades) {
this.name = name;
this.grades = new ArrayList<>(grades);
this.averageGrade = grades.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
}
public String getName() { return name; }
public List<Double> getGrades() { return new ArrayList<>(grades); }
public double getAverageGrade() { return averageGrade; }
}
}
案例2:缓存系统实现
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class LRUCache<K, V> {
private final int capacity;
private final Map<K, Node<K, V>> map;
private Node<K, V> head;
private Node<K, V> tail;
public LRUCache(int capacity) {
this.capacity = capacity;
this.map = new ConcurrentHashMap<>();
// 创建虚拟头尾节点
this.head = new Node<>(null, null);
this.tail = new Node<>(null, null);
head.next = tail;
tail.prev = head;
}
public synchronized V get(K key) {
Node<K, V> node = map.get(key);
if (node == null) {
return null;
}
// 移动到头部(最近使用)
moveToHead(node);
return node.value;
}
public synchronized void put(K key, V value) {
Node<K, V> existing = map.get(key);
if (existing != null) {
// 更新现有节点
existing.value = value;
moveToHead(existing);
} else {
// 添加新节点
Node<K, V> newNode = new Node<>(key, value);
if (map.size() >= capacity) {
// 删除尾部节点(最久未使用)
Node<K, V> tail = removeTail();
map.remove(tail.key);
}
map.put(key, newNode);
addToHead(newNode);
}
}
private void moveToHead(Node<K, V> node) {
removeNode(node);
addToHead(node);
}
private void addToHead(Node<K, V> node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(Node<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private Node<K, V> removeTail() {
Node<K, V> lastNode = tail.prev;
removeNode(lastNode);
return lastNode;
}
public synchronized int size() {
return map.size();
}
public synchronized void clear() {
map.clear();
head.next = tail;
tail.prev = head;
}
private static class Node<K, V> {
K key;
V value;
Node<K, V> prev;
Node<K, V> next;
Node(K key, V value) {
this.key = key;
this.value = value;
}
}
// 测试方法
public static void main(String[] args) {
LRUCache<String, Integer> cache = new LRUCache<>(3);
cache.put("A", 1);
cache.put("B", 2);
cache.put("C", 3);
System.out.println("A: " + cache.get("A")); // 输出: 1
cache.put("D", 4); // B被淘汰
System.out.println("B: " + cache.get("B")); // 输出: null
System.out.println("C: " + cache.get("C")); // 输出: 3
System.out.println("D: " + cache.get("D")); // 输出: 4
System.out.println("缓存大小: " + cache.size()); // 输出: 3
}
}
❓ 常见问题与解决方案
1. ConcurrentModificationException解决方案
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentModificationSolutions {
public static void main(String[] args) {
demonstrateProblem();
showSolutions();
}
private static void demonstrateProblem() {
System.out.println("=== 问题演示 ===");
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
try {
for (String item : list) {
if ("B".equals(item)) {
list.remove(item); // 抛出异常
}
}
} catch (ConcurrentModificationException e) {
System.out.println("异常: " + e.getClass().getSimpleName());
}
}
private static void showSolutions() {
System.out.println("\n=== 解决方案 ===");
// 方案1: 使用Iterator
List<String> list1 = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
Iterator<String> it = list1.iterator();
while (it.hasNext()) {
String item = it.next();
if ("B".equals(item)) {
it.remove();
}
}
System.out.println("Iterator解决方案: " + list1);
// 方案2: 反向遍历
List<String> list2 = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
for (int i = list2.size() - 1; i >= 0; i--) {
if ("B".equals(list2.get(i))) {
list2.remove(i);
}
}
System.out.println("反向遍历解决方案: " + list2);
// 方案3: 收集要删除的元素
List<String> list3 = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
List<String> toRemove = new ArrayList<>();
for (String item : list3) {
if ("B".equals(item)) {
toRemove.add(item);
}
}
list3.removeAll(toRemove);
System.out.println("收集删除解决方案: " + list3);
// 方案4: 使用Stream API
List<String> list4 = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
list4 = list4.stream()
.filter(item -> !"B".equals(item))
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println("Stream API解决方案: " + list4);
}
}
2. 集合选择指南
public class CollectionSelectionGuide {
public static void main(String[] args) {
System.out.println("=== 集合选择指南 ===");
// 场景分析
analyzeScenarios();
}
private static void analyzeScenarios() {
System.out.println("1. 需要存储有序、可重复的元素?");
System.out.println(" → 使用List接口");
System.out.println(" → 频繁随机访问:ArrayList");
System.out.println(" → 频繁插入删除:LinkedList");
System.out.println("\n2. 需要存储无重复的元素?");
System.out.println(" → 使用Set接口");
System.out.println(" → 无序,快速查找:HashSet");
System.out.println(" → 保持插入顺序:LinkedHashSet");
System.out.println(" → 需要排序:TreeSet");
System.out.println("\n3. 需要键值对映射?");
System.out.println(" → 使用Map接口");
System.out.println(" → 无序,快速访问:HashMap");
System.out.println(" → 保持插入顺序:LinkedHashMap");
System.out.println(" → 需要排序:TreeMap");
System.out.println(" → 线程安全:ConcurrentHashMap");
System.out.println("\n4. 需要队列功能?");
System.out.println(" → 使用Queue接口");
System.out.println(" → 优先队列:PriorityQueue");
System.out.println(" → 双端队列:ArrayDeque");
System.out.println(" → 阻塞队列:BlockingQueue实现类");
System.out.println("\n5. 线程安全需求?");
System.out.println(" → 传统方式:Vector, Hashtable, Collections.synchronizedXxx");
System.out.println(" → 现代方式:ConcurrentHashMap, CopyOnWriteArrayList");
System.out.println(" → 生产者消费者:BlockingQueue");
}
}
📋 总结
核心要点回顾
- 理解接口设计:Collection和Map是两大基础接口
- 选择合适实现:根据使用场景选择最优的具体实现类
- 注意线程安全:在多线程环境下选择合适的并发集合
- 性能考量:了解各种集合的时间复杂度特征
- 遍历安全:正确处理遍历时的修改操作
最佳实践建议
- 🎯 面向接口编程:声明时使用接口类型
- ⚡ 选择合适容量:避免频繁扩容影响性能
- 🔒 线程安全考虑:多线程环境使用并发集合
- 📊 性能测试验证:关键场景进行性能测试
- 🛡️ 防御性编程:注意空指针和并发修改异常
Java集合框架是Java开发的基础工具,掌握其设计思想和使用技巧,能够显著提升开发效率和代码质量。在实际应用中,根据具体需求选择合适的集合类型,并结合现代Java特性(如Stream API、Lambda表达式)来编写更优雅、高效的代码。