前言

Java集合框架是Java编程中最重要的工具之一,它提供了一套统一的接口和实现来处理对象组。集合框架不仅简化了程序设计,还提供了高性能的数据结构实现。理解集合框架的设计思想、各种集合类的特点和适用场景,对于编写高效的Java程序至关重要。本文将系统介绍Java集合框架的核心内容,帮助您全面掌握这一重要知识点。

集合框架概述

集合框架的层次结构

graph TD
    A[Collection接口] --> B[List接口]
    A --> C[Set接口]
    A --> D[Queue接口]
    
    B --> B1[ArrayList]
    B --> B2[LinkedList]
    B --> B3[Vector]
    B --> B4[Stack]
    
    C --> C1[HashSet]
    C --> C2[LinkedHashSet]
    C --> C3[TreeSet]
    C --> C4[EnumSet]
    
    D --> D1[ArrayDeque]
    D --> D2[PriorityQueue]
    D --> D3[LinkedList]
    
    E[Map接口] --> E1[HashMap]
    E --> E2[LinkedHashMap]
    E --> E3[TreeMap]
    E --> E4[Hashtable]
    E --> E5[ConcurrentHashMap]
    
    F[集合框架特点] --> F1[统一的接口设计]
    F --> F2[高性能的实现]
    F --> F3[丰富的算法支持]
    F --> F4[线程安全的选择]

集合与数组的对比

特性 数组 集合
长度 固定 可变
数据类型 基本类型+引用类型 只能存储对象
内存占用 相对较少 相对较多
便利性 操作复杂 方法丰富
类型安全 编译时检查 泛型支持

List接口及其实现

List接口特点

List是有序的集合,允许重复元素,支持索引访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.*;

public class ListDemo {
public static void main(String[] args) {
// List接口的基本特性演示
demonstrateListFeatures();

// ArrayList详解
demonstrateArrayList();

// LinkedList详解
demonstrateLinkedList();

// Vector和Stack
demonstrateVectorAndStack();

// 性能比较
performanceComparison();
}

// List基本特性
public static void demonstrateListFeatures() {
System.out.println("=== List基本特性 ===");
List<String> list = new ArrayList<>();

// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Apple"); // 允许重复
list.add(1, "Orange"); // 指定位置插入

System.out.println("列表内容:" + list);
System.out.println("大小:" + list.size());
System.out.println("索引1的元素:" + list.get(1));
System.out.println("Apple的首次出现位置:" + list.indexOf("Apple"));
System.out.println("Apple的最后出现位置:" + list.lastIndexOf("Apple"));

// 修改和删除
list.set(0, "Avocado"); // 修改
System.out.println("修改后:" + list);

list.remove("Banana"); // 按值删除
list.remove(1); // 按索引删除
System.out.println("删除后:" + list);
System.out.println();
}
}

ArrayList详解

ArrayList基于动态数组实现,查找快但插入删除慢:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class ArrayListDemo {
public static void demonstrateArrayList() {
System.out.println("=== ArrayList详解 ===");

// 创建ArrayList
ArrayList<Integer> arrayList = new ArrayList<>();
ArrayList<Integer> initializedList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

// 添加元素
for (int i = 1; i <= 5; i++) {
arrayList.add(i * 10);
}
System.out.println("ArrayList内容:" + arrayList);

// 容量管理
arrayList.ensureCapacity(20); // 确保容量
arrayList.trimToSize(); // 缩减到实际大小

// 批量操作
ArrayList<Integer> anotherList = new ArrayList<>(Arrays.asList(60, 70, 80));
arrayList.addAll(anotherList); // 添加另一个集合
System.out.println("批量添加后:" + arrayList);

arrayList.removeAll(anotherList); // 批量删除
System.out.println("批量删除后:" + arrayList);

// 查找操作
System.out.println("是否包含30:" + arrayList.contains(30));
System.out.println("是否为空:" + arrayList.isEmpty());

// 转换为数组
Integer[] array = arrayList.toArray(new Integer[0]);
System.out.println("转换为数组:" + Arrays.toString(array));

// 子列表
List<Integer> subList = arrayList.subList(1, 4);
System.out.println("子列表[1,4):" + subList);
System.out.println();
}
}

LinkedList详解

LinkedList基于双向链表实现,插入删除快但查找慢:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class LinkedListDemo {
public static void demonstrateLinkedList() {
System.out.println("=== LinkedList详解 ===");

LinkedList<String> linkedList = new LinkedList<>();

// 双端操作(Deque特性)
linkedList.addFirst("First");
linkedList.addLast("Last");
linkedList.addFirst("NewFirst");
linkedList.addLast("NewLast");

System.out.println("双端操作后:" + linkedList);

// 队列操作
linkedList.offer("Offered"); // 添加到末尾
System.out.println("队列添加后:" + linkedList);

String polled = linkedList.poll(); // 从头部取出
System.out.println("取出的元素:" + polled);
System.out.println("队列取出后:" + linkedList);

// 栈操作
linkedList.push("Pushed"); // 压入头部
System.out.println("栈压入后:" + linkedList);

String popped = linkedList.pop(); // 从头部弹出
System.out.println("弹出的元素:" + popped);
System.out.println("栈弹出后:" + linkedList);

// 查看操作(不删除)
System.out.println("头部元素:" + linkedList.peekFirst());
System.out.println("尾部元素:" + linkedList.peekLast());

// 删除特定元素
linkedList.removeFirstOccurrence("Last");
linkedList.removeLastOccurrence("NewLast");
System.out.println("删除特定元素后:" + linkedList);
System.out.println();
}
}

性能比较

graph TD
    A[List实现类性能对比] --> B[随机访问]
    A --> C[顺序访问]
    A --> D[插入删除]
    A --> E[内存占用]
    
    B --> B1[ArrayList: O1]
    B --> B2[LinkedList: On]
    B --> B3[Vector: O1]
    
    C --> C1[ArrayList: 很快]
    C --> C2[LinkedList: 较快]
    C --> C3[Vector: 很快]
    
    D --> D1[ArrayList头部/中间: On]
    D --> D2[ArrayList尾部: O1]
    D --> D3[LinkedList头尾: O1]
    D --> D4[LinkedList中间: On]
    
    E --> E1[ArrayList: 较少]
    E --> E2[LinkedList: 较多]
    E --> E3[Vector: 较少]

Set接口及其实现

Set接口特点

Set不允许重复元素,主要用于去重和集合运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.*;

public class SetDemo {
public static void main(String[] args) {
demonstrateSetFeatures();
demonstrateHashSet();
demonstrateLinkedHashSet();
demonstrateTreeSet();
setOperations();
}

// Set基本特性
public static void demonstrateSetFeatures() {
System.out.println("=== Set基本特性 ===");
Set<String> set = new HashSet<>();

// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复元素,不会被添加
set.add("Cherry");

System.out.println("Set内容:" + set);
System.out.println("大小:" + set.size());
System.out.println("是否包含Apple:" + set.contains("Apple"));

// 遍历Set
System.out.print("遍历元素:");
for (String fruit : set) {
System.out.print(fruit + " ");
}
System.out.println("\n");
}
}

HashSet详解

HashSet基于哈希表实现,无序但查找效率高:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class HashSetDemo {
public static void demonstrateHashSet() {
System.out.println("=== HashSet详解 ===");

HashSet<Integer> hashSet = new HashSet<>();

// 添加元素
for (int i = 10; i >= 1; i--) {
hashSet.add(i);
}
hashSet.add(5); // 重复元素

System.out.println("HashSet内容(无序):" + hashSet);

// 自定义对象的HashSet
Set<Person> personSet = new HashSet<>();
personSet.add(new Person("Alice", 25));
personSet.add(new Person("Bob", 30));
personSet.add(new Person("Alice", 25)); // 如果equals和hashCode正确实现,则重复

System.out.println("Person Set大小:" + personSet.size());
System.out.println();
}
}

class Person {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}

@Override
public String toString() {
return name + "(" + age + ")";
}
}

TreeSet详解

TreeSet基于红黑树实现,元素有序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class TreeSetDemo {
public static void demonstrateTreeSet() {
System.out.println("=== TreeSet详解 ===");

// 自然排序
TreeSet<Integer> treeSet = new TreeSet<>();
int[] numbers = {5, 2, 8, 1, 9, 3};
for (int num : numbers) {
treeSet.add(num);
}
System.out.println("TreeSet内容(自然排序):" + treeSet);

// 定制排序
TreeSet<String> customSorted = new TreeSet<>((s1, s2) -> s2.compareTo(s1)); // 逆序
customSorted.addAll(Arrays.asList("banana", "apple", "cherry", "date"));
System.out.println("自定义排序:" + customSorted);

// 导航方法
System.out.println("第一个元素:" + treeSet.first());
System.out.println("最后一个元素:" + treeSet.last());
System.out.println("小于5的最大元素:" + treeSet.lower(5));
System.out.println("大于等于5的最小元素:" + treeSet.ceiling(5));

// 子集操作
System.out.println("子集[2,8):" + treeSet.subSet(2, 8));
System.out.println("头部集合(<5):" + treeSet.headSet(5));
System.out.println("尾部集合(>=5):" + treeSet.tailSet(5));
System.out.println();
}
}

集合运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SetOperations {
public static void setOperations() {
System.out.println("=== 集合运算 ===");

Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8));

System.out.println("集合1:" + set1);
System.out.println("集合2:" + set2);

// 并集
Set<Integer> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println("并集:" + union);

// 交集
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println("交集:" + intersection);

// 差集
Set<Integer> difference = new HashSet<>(set1);
difference.removeAll(set2);
System.out.println("差集(1-2):" + difference);

// 对称差集
Set<Integer> symmetricDiff = new HashSet<>(union);
symmetricDiff.removeAll(intersection);
System.out.println("对称差集:" + symmetricDiff);
System.out.println();
}
}

Map接口及其实现

Map接口特点

Map存储键值对,键唯一但值可重复:

graph TD
    A[Map接口特点] --> B[键值对存储]
    A --> C[键的唯一性]
    A --> D[值可重复]
    A --> E[基于键的快速查找]
    
    B --> B1[Entry对象]
    B --> B2[Key-Value关联]
    
    C --> C1[基于equals和hashCode]
    C --> C2[重复键会覆盖值]
    
    D --> D1[多个键可指向同一值]
    D --> D2[null值的处理]
    
    E --> E1[HashMap: O1平均]
    E --> E2[TreeMap: O log n]
    E --> E3[LinkedHashMap: O1平均]
    
    F[Map实现类对比] --> F1[HashMap无序高性能]
    F --> F2[LinkedHashMap维持插入顺序]
    F --> F3[TreeMap有序基于比较]
    F --> F4[Hashtable线程安全遗留类]

HashMap详解

HashMap是最常用的Map实现,基于哈希表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import java.util.*;

public class HashMapDemo {
public static void demonstrateHashMap() {
System.out.println("=== HashMap详解 ===");

HashMap<String, Integer> map = new HashMap<>();

// 添加键值对
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 15);
map.put("apple", 12); // 覆盖之前的值

System.out.println("HashMap内容:" + map);
System.out.println("苹果数量:" + map.get("apple"));
System.out.println("是否包含香蕉:" + map.containsKey("banana"));
System.out.println("是否包含数量15:" + map.containsValue(15));

// 安全获取值
System.out.println("葡萄数量:" + map.getOrDefault("grape", 0));

// 条件操作
map.putIfAbsent("grape", 25); // 键不存在时才添加
map.replace("banana", 20, 22); // 值匹配时才替换

System.out.println("条件操作后:" + map);

// 遍历方式
System.out.println("\n遍历键值对:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}

System.out.println("\n遍历键:");
for (String key : map.keySet()) {
System.out.println(key + " -> " + map.get(key));
}

System.out.println("\n遍历值:");
for (Integer value : map.values()) {
System.out.print(value + " ");
}
System.out.println("\n");

// Lambda表达式操作
map.forEach((key, value) -> System.out.println(key + ": " + value));

// 计算操作
map.compute("apple", (key, value) -> value * 2);
map.computeIfAbsent("kiwi", key -> 30);
map.computeIfPresent("banana", (key, value) -> value + 5);

System.out.println("计算操作后:" + map);
System.out.println();
}

public static void main(String[] args) {
demonstrateHashMap();
demonstrateLinkedHashMap();
demonstrateTreeMap();
mapPerformanceDemo();
}

// LinkedHashMap:维持插入顺序
public static void demonstrateLinkedHashMap() {
System.out.println("=== LinkedHashMap详解 ===");

LinkedHashMap<String, Integer> linkedMap = new LinkedHashMap<>();
linkedMap.put("third", 3);
linkedMap.put("first", 1);
linkedMap.put("second", 2);

System.out.println("LinkedHashMap(保持插入顺序):" + linkedMap);

// LRU缓存实现
LinkedHashMap<String, String> lruCache = new LinkedHashMap<String, String>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > 3; // 最多保存3个元素
}
};

lruCache.put("A", "Value A");
lruCache.put("B", "Value B");
lruCache.put("C", "Value C");
System.out.println("LRU缓存:" + lruCache);

lruCache.get("A"); // 访问A,使其成为最近使用
lruCache.put("D", "Value D"); // 添加D,最老的B应该被移除
System.out.println("访问A后添加D:" + lruCache);
System.out.println();
}

// TreeMap:有序Map
public static void demonstrateTreeMap() {
System.out.println("=== TreeMap详解 ===");

TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("banana", 2);
treeMap.put("apple", 1);
treeMap.put("cherry", 3);
treeMap.put("date", 4);

System.out.println("TreeMap(自然排序):" + treeMap);

// 导航方法
System.out.println("第一个键:" + treeMap.firstKey());
System.out.println("最后一个键:" + treeMap.lastKey());
System.out.println("小于'cherry'的最大键:" + treeMap.lowerKey("cherry"));
System.out.println("大于等于'cherry'的最小键:" + treeMap.ceilingKey("cherry"));

// 子Map
System.out.println("子Map[apple, date):" + treeMap.subMap("apple", "date"));
System.out.println("头部Map(<cherry):" + treeMap.headMap("cherry"));
System.out.println("尾部Map(>=cherry):" + treeMap.tailMap("cherry"));

// 自定义排序
TreeMap<Integer, String> customTreeMap = new TreeMap<>(Collections.reverseOrder());
customTreeMap.put(1, "One");
customTreeMap.put(3, "Three");
customTreeMap.put(2, "Two");
System.out.println("自定义排序(逆序):" + customTreeMap);
System.out.println();
}

// Map性能演示
public static void mapPerformanceDemo() {
System.out.println("=== Map性能对比 ===");
int size = 100000;

// HashMap性能测试
long start = System.nanoTime();
Map<Integer, String> hashMap = new HashMap<>();
for (int i = 0; i < size; i++) {
hashMap.put(i, "Value" + i);
}
long hashMapTime = System.nanoTime() - start;

// TreeMap性能测试
start = System.nanoTime();
Map<Integer, String> treeMap = new TreeMap<>();
for (int i = 0; i < size; i++) {
treeMap.put(i, "Value" + i);
}
long treeMapTime = System.nanoTime() - start;

// LinkedHashMap性能测试
start = System.nanoTime();
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
for (int i = 0; i < size; i++) {
linkedHashMap.put(i, "Value" + i);
}
long linkedHashMapTime = System.nanoTime() - start;

System.out.printf("插入%d个元素的时间对比:%n", size);
System.out.printf("HashMap: %.2f ms%n", hashMapTime / 1_000_000.0);
System.out.printf("TreeMap: %.2f ms%n", treeMapTime / 1_000_000.0);
System.out.printf("LinkedHashMap: %.2f ms%n", linkedHashMapTime / 1_000_000.0);
System.out.println();
}
}

迭代器和增强for循环

Iterator接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import java.util.*;

public class IteratorDemo {
public static void main(String[] args) {
demonstrateIterator();
demonstrateListIterator();
safeDeletion();
}

// 基本迭代器使用
public static void demonstrateIterator() {
System.out.println("=== Iterator使用 ===");

List<String> list = Arrays.asList("A", "B", "C", "D", "E");

// 使用Iterator遍历
Iterator<String> iterator = list.iterator();
System.out.print("Iterator遍历:");
while (iterator.hasNext()) {
String element = iterator.next();
System.out.print(element + " ");
}
System.out.println();

// 增强for循环(语法糖)
System.out.print("增强for循环:");
for (String element : list) {
System.out.print(element + " ");
}
System.out.println();

// Stream API遍历
System.out.print("Stream遍历:");
list.stream().forEach(element -> System.out.print(element + " "));
System.out.println("\n");
}

// ListIterator双向迭代
public static void demonstrateListIterator() {
System.out.println("=== ListIterator使用 ===");

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ListIterator<Integer> listIterator = list.listIterator();

// 正向遍历
System.out.print("正向遍历:");
while (listIterator.hasNext()) {
System.out.print(listIterator.next() + " ");
}
System.out.println();

// 反向遍历
System.out.print("反向遍历:");
while (listIterator.hasPrevious()) {
System.out.print(listIterator.previous() + " ");
}
System.out.println();

// 在迭代过程中修改
listIterator = list.listIterator();
while (listIterator.hasNext()) {
Integer num = listIterator.next();
if (num % 2 == 0) {
listIterator.set(num * 10); // 修改偶数
}
}
System.out.println("修改后的列表:" + list);
System.out.println();
}

// 安全删除演示
public static void safeDeletion() {
System.out.println("=== 安全删除元素 ===");

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

// 错误方式:ConcurrentModificationException
/*
for (Integer num : list) {
if (num % 2 == 0) {
list.remove(num); // 会抛出异常
}
}
*/

// 正确方式1:使用Iterator
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer num = iterator.next();
if (num % 2 == 0) {
iterator.remove(); // 安全删除
}
}
System.out.println("删除偶数后(Iterator):" + list);

// 重新初始化列表
list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

// 正确方式2:倒序遍历
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) % 2 == 0) {
list.remove(i);
}
}
System.out.println("删除偶数后(倒序):" + list);

// 重新初始化列表
list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

// 正确方式3:使用removeIf
list.removeIf(num -> num % 2 == 0);
System.out.println("删除偶数后(removeIf):" + list);
System.out.println();
}
}

Collections工具类

常用算法和操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import java.util.*;

public class CollectionsDemo {
public static void main(String[] args) {
sortingOperations();
searchingOperations();
collectionOperations();
synchronizedCollections();
unmodifiableCollections();
}

// 排序操作
public static void sortingOperations() {
System.out.println("=== 排序操作 ===");

List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 2, 8, 1, 9, 3));
System.out.println("原始列表:" + numbers);

// 自然排序
Collections.sort(numbers);
System.out.println("自然排序:" + numbers);

// 逆序排序
Collections.sort(numbers, Collections.reverseOrder());
System.out.println("逆序排序:" + numbers);

// 自定义排序
List<String> words = new ArrayList<>(Arrays.asList("banana", "apple", "cherry", "date"));
Collections.sort(words, (s1, s2) -> s1.length() - s2.length());
System.out.println("按长度排序:" + words);

// 打乱顺序
Collections.shuffle(numbers);
System.out.println("打乱顺序:" + numbers);

// 旋转
Collections.rotate(numbers, 2);
System.out.println("右旋转2位:" + numbers);

// 反转
Collections.reverse(numbers);
System.out.println("反转:" + numbers);
System.out.println();
}

// 查找操作
public static void searchingOperations() {
System.out.println("=== 查找操作 ===");

List<Integer> numbers = Arrays.asList(1, 3, 5, 7, 9, 11, 13, 15);
System.out.println("有序列表:" + numbers);

// 二分查找
int index = Collections.binarySearch(numbers, 7);
System.out.println("查找7的位置:" + index);

index = Collections.binarySearch(numbers, 6);
System.out.println("查找6的位置(不存在):" + index);

// 最大最小值
System.out.println("最大值:" + Collections.max(numbers));
System.out.println("最小值:" + Collections.min(numbers));

// 频率统计
List<String> letters = Arrays.asList("a", "b", "a", "c", "a", "b");
System.out.println("字母a出现次数:" + Collections.frequency(letters, "a"));
System.out.println();
}

// 集合操作
public static void collectionOperations() {
System.out.println("=== 集合操作 ===");

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
System.out.println("原始列表:" + list);

// 填充
Collections.fill(list, "X");
System.out.println("填充后:" + list);

// 重新初始化
list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));

// 替换
Collections.replaceAll(list, "B", "Y");
System.out.println("替换B为Y:" + list);

// 交换
Collections.swap(list, 0, 4);
System.out.println("交换位置0和4:" + list);

// 复制
List<String> copy = new ArrayList<>(Collections.nCopies(list.size(), ""));
Collections.copy(copy, list);
System.out.println("复制的列表:" + copy);

// 不相交检查
List<String> list1 = Arrays.asList("A", "B", "C");
List<String> list2 = Arrays.asList("D", "E", "F");
System.out.println("列表不相交:" + Collections.disjoint(list1, list2));
System.out.println();
}

// 同步集合
public static void synchronizedCollections() {
System.out.println("=== 同步集合 ===");

// 创建同步集合
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());

syncList.add("Thread-Safe List");
syncSet.add("Thread-Safe Set");
syncMap.put("key", "Thread-Safe Map");

System.out.println("同步列表:" + syncList);
System.out.println("同步集合:" + syncSet);
System.out.println("同步映射:" + syncMap);

// 注意:遍历时仍需手动同步
synchronized (syncList) {
for (String item : syncList) {
System.out.println("安全遍历:" + item);
}
}
System.out.println();
}

// 不可修改集合
public static void unmodifiableCollections() {
System.out.println("=== 不可修改集合 ===");

List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> immutableList = Collections.unmodifiableList(mutableList);

System.out.println("不可修改列表:" + immutableList);

try {
immutableList.add("D"); // 会抛出UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("无法修改不可变集合:" + e.getMessage());
}

// 注意:原集合的修改会反映到不可修改视图
mutableList.add("D");
System.out.println("修改原集合后的不可修改视图:" + immutableList);

// 真正的不可变集合(Java 9+)
List<String> trulyImmutable = List.of("X", "Y", "Z");
System.out.println("真正的不可变列表:" + trulyImmutable);
System.out.println();
}
}

集合的选择指南

选择决策树

graph TD
    A[选择集合类型] --> B{是否需要键值对?}
    B -->|是| C[选择Map]
    B -->|否| D{是否允许重复?}
    
    C --> C1{是否需要排序?}
    C1 -->|是| C11[TreeMap]
    C1 -->|否| C12{是否需要插入顺序?}
    C12 -->|是| C121[LinkedHashMap]
    C12 -->|否| C122[HashMap]
    
    D -->|允许| E[选择List]
    D -->|不允许| F[选择Set]
    
    E --> E1{访问模式?}
    E1 -->|随机访问多| E11[ArrayList]
    E1 -->|插入删除多| E12[LinkedList]
    
    F --> F1{是否需要排序?}
    F1 -->|是| F11[TreeSet]
    F1 -->|否| F12{是否需要插入顺序?}
    F12 -->|是| F121[LinkedHashSet]
    F12 -->|否| F122[HashSet]
    
    G[性能考虑] --> G1[ArrayList: 随机访问O1]
    G --> G2[LinkedList: 插入删除O1]
    G --> G3[HashMap: 查找O1平均]
    G --> G4[TreeMap: 查找O log n]
    G --> G5[HashSet: 查找O1平均]
    G --> G6[TreeSet: 查找O log n]

总结

Java集合框架是Java编程的核心组件,本文全面介绍了集合框架的主要内容:

  1. 框架概述:理解集合框架的设计思想和层次结构
  2. List接口:掌握ArrayList、LinkedList等实现的特点和应用
  3. Set接口:学会使用HashSet、TreeSet进行去重和集合运算
  4. Map接口:熟练使用HashMap、TreeMap等进行键值对存储
  5. 迭代器:理解Iterator和ListIterator的使用方法
  6. 工具类:掌握Collections类提供的算法和操作
  7. 选择指南:学会根据需求选择合适的集合类型

合理选择和使用集合类型对程序性能和可维护性至关重要。在实际开发中,应该根据数据特点、访问模式和性能要求来选择最适合的集合实现,同时注意线程安全性和内存使用效率。

参考资料

  1. Oracle Java Documentation - Collections Framework
  2. Effective Java by Joshua Bloch
  3. Java核心技术卷I - 集合框架
  4. Java集合框架源码分析
    abbrlink: 3