深入理解 Java 集合框架 - 详解
2025-09-16 10:01 tlnshuju 阅读(87) 评论(0) 收藏 举报目录
7.2 ArrayList 和 LinkedList 的区别
Java 集合框架(Java Collections Framework)是 Java 语言中最重要的组成部分之一。
1. 集合框架概述
1.1 什么是集合框架?
Java 集合框架是一组用于表示和操作集合的统一架构,包含:
- 接口:定义集合的基本操作
- 实现:接口的具体实现类
- 算法:对集合进行操作的方法(如排序、搜索)
1.2 集合框架的体系结构
Collection
├── List (有序、可重复)
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
│ └── Stack
│
├── Set (无序、不可重复)
│ ├── HashSet
│ │ └── LinkedHashSet
│ ├── TreeSet
│ └── EnumSet
│
└── Queue (队列)
├── PriorityQueue
├── ArrayDeque
└── LinkedList
Map (键值对)
├── HashMap
│ └── LinkedHashMap
├── TreeMap
├── Hashtable
│ └── Properties
└── EnumMap
2. Collection 接口及其实现
2.1 List 接口
ArrayList
// ArrayList 示例
List arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
arrayList.add("C++");
// 随机访问高效
System.out.println(arrayList.get(1)); // 输出: Python
// 遍历
for (String language : arrayList) {
System.out.println(language);
}
// 特点:基于数组,随机访问快,插入删除慢(需要移动元素)
LinkedList
// LinkedList 示例
List linkedList = new LinkedList<>();
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.addFirst("Orange"); // 在开头添加
// 插入删除高效
linkedList.remove(1); // 删除第二个元素
// 特点:基于双向链表,插入删除快,随机访问慢
Vector vs ArrayList
// Vector 是线程安全的,但性能较差
Vector vector = new Vector<>();
vector.add("item1");
vector.add("item2");
// ArrayList 非线程安全,但性能更好
List arrayList = new ArrayList<>();
2.2 Set 接口
HashSet
// HashSet 示例
Set hashSet = new HashSet<>();
hashSet.add("北京");
hashSet.add("上海");
hashSet.add("北京"); // 重复元素不会被添加
System.out.println(hashSet); // 输出: [北京, 上海]
System.out.println(hashSet.contains("上海")); // true
// 特点:基于HashMap,无序,查询速度快
LinkedHashSet
// LinkedHashSet 保持插入顺序
Set linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("第一");
linkedHashSet.add("第二");
linkedHashSet.add("第三");
System.out.println(linkedHashSet); // 输出: [第一, 第二, 第三]
TreeSet
// TreeSet 自然排序
Set treeSet = new TreeSet<>();
treeSet.add("orange");
treeSet.add("apple");
treeSet.add("banana");
System.out.println(treeSet); // 输出: [apple, banana, orange]
// 自定义排序
Set customSet = new TreeSet<>(Comparator.reverseOrder());
customSet.add(5);
customSet.add(1);
customSet.add(10);
System.out.println(customSet); // 输出: [10, 5, 1]
2.3 Queue 接口
PriorityQueue
// 优先级队列
Queue priorityQueue = new PriorityQueue<>();
priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(10);
while (!priorityQueue.isEmpty()) {
System.out.println(priorityQueue.poll()); // 输出: 1, 5, 10
}
ArrayDeque
// 双端队列
Deque deque = new ArrayDeque<>();
deque.offerFirst("first");
deque.offerLast("last");
deque.offer("middle");
System.out.println(deque.pollFirst()); // 输出: first
System.out.println(deque.pollLast()); // 输出: last
3. Map 接口及其实现
3.1 HashMap
// HashMap 示例
Map hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put("Charlie", 28);
// 获取值
System.out.println(hashMap.get("Alice")); // 输出: 25
// 遍历
for (Map.Entry entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Java 8+ 方法
hashMap.forEach((k, v) -> System.out.println(k + ": " + v));
3.2 LinkedHashMap
// 保持插入顺序的Map
Map linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("z", 1);
linkedHashMap.put("a", 2);
linkedHashMap.put("b", 3);
System.out.println(linkedHashMap.keySet()); // 输出: [z, a, b]
3.3 TreeMap
// 排序的Map
Map treeMap = new TreeMap<>();
treeMap.put("orange", 1);
treeMap.put("apple", 2);
treeMap.put("banana", 3);
System.out.println(treeMap.keySet()); // 输出: [apple, banana, orange]
3.4 Hashtable vs HashMap
// Hashtable 是线程安全的
Map hashtable = new Hashtable<>();
hashtable.put("key", "value");
// HashMap 非线程安全,但性能更好
Map hashMap = new HashMap<>();
4. 集合的线程安全版本
4.1 同步包装器
// 创建线程安全的集合
List syncList = Collections.synchronizedList(new ArrayList<>());
Set syncSet = Collections.synchronizedSet(new HashSet<>());
Map syncMap = Collections.synchronizedMap(new HashMap<>());
4.2 Concurrent 集合(Java 5+)
// 并发集合,性能更好
ConcurrentHashMap concurrentMap = new ConcurrentHashMap<>();
CopyOnWriteArrayList copyOnWriteList = new CopyOnWriteArrayList<>();
ConcurrentLinkedQueue concurrentQueue = new ConcurrentLinkedQueue<>();
5. 集合的性能比较
5.1 List 性能比较
操作 | ArrayList | LinkedList |
随机访问 | O(1) | O(n) |
头部插入 | O(n) | O(1) |
尾部插入 | O(1) | O(1) |
中间插入 | O(n) | O(n) |
删除 | O(n) | O(1) |
5.2 Set 性能比较
操作 | HashSet | TreeSet | LinkedHashSet |
添加 | O(1) | O(log n) | O(1) |
包含 | O(1) | O(log n) | O(1) |
删除 | O(1) | O(log n) | O(1) |
有序 | 否 | 是 | 插入顺序 |
5.3 Map 性能比较
操作 | HashMap | TreeMap | LinkedHashMap |
添加 | O(1) | O(log n) | O(1) |
获取 | O(1) | O(log n) | O(1) |
删除 | O(1) | O(log n) | O(1) |
有序 | 否 | 是 | 插入顺序 |
6. 集合的最佳实践
6.1 选择合适的集合
// 根据需求选择集合类型
if (需要快速随机访问) {
return new ArrayList<>();
} else if (需要频繁插入删除) {
return new LinkedList<>();
} else if (需要去重) {
return new HashSet<>();
} else if (需要键值对) {
return new HashMap<>();
} else if (需要排序) {
return new TreeSet<>(); // 或 TreeMap
}
6.2 初始化容量
// 预估大小,避免扩容开销
List list = new ArrayList<>(1000);
Map map = new HashMap<>(1024, 0.75f);
6.3 使用增强for循环和迭代器
// 推荐写法
for (String item : collection) {
System.out.println(item);
}
// 需要删除时使用迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (shouldRemove(item)) {
iterator.remove(); // 安全的删除方式
}
}
6.4 Java 8+ 新特性
// Stream API
List filtered = list.stream()
.filter(s -> s.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());
// computeIfAbsent
Map> map = new HashMap<>();
map.computeIfAbsent("key", k -> new ArrayList<>()).add("value");
7. 常见面试问题
7.1 HashMap 的工作原理
HashMap 基于数组+链表/红黑树实现,通过 hashCode() 计算存储位置,使用 equals() 解决哈希冲突。
7.2 ArrayList 和 LinkedList 的区别
- ArrayList 基于数组,随机访问快
- LinkedList 基于链表,插入删除快
7.3 ConcurrentHashMap 的实现原理
使用分段锁(Java 7)或 CAS + synchronized(Java 8),提高并发性能。
8. 总结
Java 集合框架提供了丰富的数据结构和算法,理解它们的特性和适用场景对于编写高效代码至关重要:
关键要点:
- 根据需求选择集合:考虑性能、线程安全、排序需求
- 理解底层实现:知道不同集合的时间复杂度
- 注意线程安全:多线程环境使用并发集合或同步包装器
- 利用新特性:Java 8+ 的 Stream API 和 Lambda 表达式
选择使用:
- List:需要有序、可重复的元素
- Set:需要去重、快速查找
- Map:需要键值对存储
- Queue:需要队列操作
浙公网安备 33010602011771号