Java 集合框架
Java 集合框架(Collections Framework)是 Java 提供的用于存储和操作一组对象的数据结构。它提供了一套统一的标准接口和实现类,使开发者能够方便地对数据进行存储、检索和操作。
集合框架概述
Java 集合框架主要包括以下组成部分:
- 接口:定义了不同类型集合的抽象数据类型
- 实现类:提供了接口的具体实现
- 算法:用于对集合进行排序、搜索等操作的静态方法
集合框架的优势
根据 Oracle 官方文档,集合框架提供以下优势:
- 减少编程工作量:提供了现成的数据结构和算法,无需自行实现
- 提高性能:提供了高质量的数据结构实现,可以轻松切换不同实现来优化性能
- 提供互操作性:不同 API 之间可以通过标准接口传递集合
- 降低学习成本:只需学习统一的集合 API
- 促进代码复用:提供标准的接口和实现
集合框架层次结构
Iterable
├── Collection
│ ├── List(有序、可重复)
│ │ ├── ArrayList
│ │ ├── LinkedList
│ │ └── Vector
│ ├── Set(无序、不可重复)
│ │ ├── HashSet
│ │ ├── LinkedHashSet
│ │ └── TreeSet
│ └── Queue(队列)
│ ├── LinkedList
│ └── PriorityQueue
└── Map(键值对)
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable
List 接口
List 是有序集合(也称为序列),可以精确控制每个元素的位置,允许重复元素。List 接口定义了按索引访问元素的能力。
ArrayList
ArrayList 是最常用的 List 实现类,基于动态数组实现。它实现了 RandomAccess 标记接口,表示支持快速随机访问。
底层实现原理
ArrayList 内部使用一个 Object 数组来存储元素:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
// 存储元素的数组
transient Object[] elementData;
// 实际元素个数
private int size;
}
扩容机制
当添加元素时,如果数组已满,ArrayList 会自动扩容:
// 扩容计算:新容量 = 旧容量 + 旧容量 >> 1(即 1.5 倍)
int newCapacity = oldCapacity + (oldCapacity >> 1);
扩容过程:
- 创建一个更大的新数组(原容量的 1.5 倍)
- 将原数组的元素复制到新数组
- 将新元素添加到新数组
扩容示例:
import java.util.ArrayList;
// 创建初始容量为 10 的 ArrayList
ArrayList<Integer> list = new ArrayList<>(10);
// 添加元素触发扩容
for (int i = 0; i < 15; i++) {
list.add(i);
// 当添加第 11 个元素时,容量从 10 扩展到 15
}
基本操作
import java.util.ArrayList;
import java.util.List;
List<String> list = new ArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Orange");
list.add(1, "Grape"); // 在指定位置插入
// 访问元素
String first = list.get(0); // Apple
int size = list.size(); // 4
// 修改元素
list.set(0, "Pear"); // 将第一个元素改为 Pear
// 删除元素
list.remove(0); // 删除第一个元素
list.remove("Banana"); // 删除指定元素
// 遍历方式
// 方式1:for 循环(推荐用于 ArrayList,因为支持随机访问)
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 方式2:增强 for 循环
for (String item : list) {
System.out.println(item);
}
// 方式3:迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
// 方式4:forEach 方法(Java 8+)
list.forEach(System.out::println);
时间复杂度分析
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| get(int index) | O(1) | 直接通过索引访问 |
| set(int index, E e) | O(1) | 直接通过索引修改 |
| add(E e) | O(1) 平均 | 尾部添加,扩容时为 O(n) |
| add(int index, E e) | O(n) | 需要移动后续元素 |
| remove(int index) | O(n) | 需要移动后续元素 |
| contains(Object o) | O(n) | 需要遍历查找 |
LinkedList
LinkedList 基于双向链表实现,适合频繁的插入和删除操作。它同时实现了 List 和 Deque 接口。
底层实现原理
LinkedList 内部使用双向链表存储元素:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
// 链表长度
transient int size = 0;
// 头节点
transient Node<E> first;
// 尾节点
transient Node<E> last;
// 节点内部类
private static class Node<E> {
E item; // 元素值
Node<E> next; // 后继节点
Node<E> prev; // 前驱节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}
基本操作
import java.util.LinkedList;
import java.util.List;
LinkedList<String> linkedList = new LinkedList<>();
// 基本操作
linkedList.add("A");
linkedList.addFirst("First"); // 添加到头部,O(1)
linkedList.addLast("Last"); // 添加到尾部,O(1)
linkedList.removeFirst(); // 移除头部,O(1)
linkedList.removeLast(); // 移除尾部,O(1)
// 作为队列使用
linkedList.offer("B"); // 添加到尾部
String head = linkedList.poll(); // 移除头部
// 作为栈使用
linkedList.push("C"); // 压栈(添加到头部)
String top = linkedList.pop(); // 出栈(移除头部)
时间复杂度分析
| 操作 | 时间复杂度 | 说明 |
|---|---|---|
| get(int index) | O(n) | 需要从头或尾遍历 |
| addFirst(E e) | O(1) | 直接操作头节点 |
| addLast(E e) | O(1) | 直接操作尾节点 |
| removeFirst() | O(1) | 直接操作头节点 |
| removeLast() | O(1) | 直接操作尾节点 |
| add(int index, E e) | O(n) | 需要先遍历找到位置 |
ArrayList vs LinkedList 性能对比
实际性能分析:虽然从算法复杂度看,LinkedList 的中间插入应该是 O(1),但在实际运行中,ArrayList 往往表现更好。
原因:
- CPU 缓存友好性:ArrayList 的连续内存布局更适合 CPU 缓存预取
- 指针跳转开销:LinkedList 需要频繁的指针跳转,无法命中 CPU 缓存
- 内存开销:LinkedList 每个节点需要额外存储两个指针
// 性能测试示例
import java.util.*;
public class ListPerformanceTest {
public static void main(String[] args) {
int size = 100000;
// ArrayList 测试
List<Integer> arrayList = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
arrayList.add(0, i); // 头部插入
}
System.out.println("ArrayList 头部插入: " + (System.currentTimeMillis() - start) + "ms");
// LinkedList 测试
List<Integer> linkedList = new LinkedList<>();
start = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
linkedList.add(0, i); // 头部插入
}
System.out.println("LinkedList 头部插入: " + (System.currentTimeMillis() - start) + "ms");
}
}
选择建议:
| 场景 | 推荐 |
|---|---|
| 随机访问频繁 | ArrayList |
| 尾部添加/删除 | ArrayList |
| 头部添加/删除 | LinkedList |
| 中间插入/删除(已知位置) | LinkedList |
| 内存敏感 | ArrayList |
Vector
Vector 是线程安全的 ArrayList,所有方法都使用 synchronized 修饰。由于性能较差,现在很少使用,推荐使用 Collections.synchronizedList() 或 CopyOnWriteArrayList。
import java.util.Vector;
Vector<String> vector = new Vector<>();
vector.add("A");
vector.addElement("B"); // 旧方法,效果同 add
// 推荐使用线程安全的替代方案
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
List 常用方法
| 方法 | 说明 |
|---|---|
add(E e) | 添加元素到末尾 |
add(int index, E e) | 在指定位置添加元素 |
get(int index) | 获取指定位置的元素 |
set(int index, E e) | 修改指定位置的元素 |
remove(int index) | 删除指定位置的元素 |
remove(Object o) | 删除第一个匹配的元素 |
size() | 返回元素个数 |
contains(Object o) | 判断是否包含元素 |
indexOf(Object o) | 返回第一个匹配元素的索引 |
clear() | 清空所有元素 |
isEmpty() | 判断是否为空 |
subList(int from, int to) | 返回子列表 |
Set 接口
Set 是不允许重复元素的集合,主要用于去重。Set 不保证元素的顺序(LinkedHashSet 和 TreeSet 除外)。
HashSet
HashSet 基于哈希表实现,是 Set 接口最常用的实现类。
底层实现原理
HashSet 内部使用 HashMap 来存储元素:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
// 使用 HashMap 存储
private transient HashMap<E,Object> map;
// 虚拟值,作为 HashMap 的 value
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
}
元素存储在 HashMap 的 key 中,value 是一个固定的 Object 对象。
基本操作
import java.util.HashSet;
import java.util.Set;
Set<String> set = new HashSet<>();
// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复元素不会被添加,返回 false
// 检查元素
boolean hasApple = set.contains("Apple"); // true
int size = set.size(); // 2
// 删除元素
set.remove("Apple");
// 遍历
for (String item : set) {
System.out.println(item);
}
元素唯一性保证
HashSet 通过 hashCode() 和 equals() 方法来判断元素是否重复:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 必须重写 hashCode 和 equals
@Override
public int hashCode() {
return Objects.hash(name, 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);
}
}
// 使用示例
Set<Person> persons = new HashSet<>();
persons.add(new Person("张三", 25));
persons.add(new Person("张三", 25)); // 不会被添加(如果正确重写了 hashCode 和 equals)
LinkedHashSet
LinkedHashSet 继承自 HashSet,维护元素的插入顺序。
import java.util.LinkedHashSet;
LinkedHashSet<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("First");
linkedSet.add("Second");
linkedSet.add("Third");
// 遍历顺序:First, Second, Third(保持插入顺序)
TreeSet
TreeSet 基于红黑树实现,会自动对元素进行排序(自然顺序或自定义顺序)。
import java.util.TreeSet;
import java.util.Set;
import java.util.Comparator;
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(5);
treeSet.add(2);
treeSet.add(8);
treeSet.add(1);
// 遍历顺序:1, 2, 5, 8(自动升序)
// 使用自定义比较器
Set<String> treeSet2 = new TreeSet<>(Comparator.reverseOrder());
treeSet2.add("Apple");
treeSet2.add("Banana");
treeSet2.add("Orange");
// 遍历顺序:Orange, Banana, Apple(降序)
// 自定义对象排序
class Student implements Comparable<Student> {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
return Integer.compare(other.score, this.score); // 按分数降序
}
}
Set<Student> students = new TreeSet<>();
students.add(new Student("张三", 85));
students.add(new Student("李四", 92));
students.add(new Student("王五", 78));
Set 常用方法
| 方法 | 说明 |
|---|---|
add(E e) | 添加元素,如果已存在则返回 false |
remove(Object o) | 删除元素 |
contains(Object o) | 判断是否包含元素 |
size() | 返回元素个数 |
isEmpty() | 判断是否为空 |
clear() | 清空所有元素 |
iterator() | 返回迭代器 |
Queue 接口
Queue 是队列接口,用于存储待处理的元素,遵循先进先出(FIFO)原则。
PriorityQueue
PriorityQueue 是优先级队列,元素按自然顺序或自定义顺序排列。
import java.util.PriorityQueue;
import java.util.Queue;
Queue<Integer> pq = new PriorityQueue<>();
pq.add(5);
pq.add(2);
pq.add(8);
pq.add(1);
System.out.println(pq.poll()); // 1(最小元素)
System.out.println(pq.poll()); // 2
System.out.println(pq.poll()); // 5
Deque(双端队列)
Deque 继承自 Queue,支持在两端添加和删除元素。
import java.util.ArrayDeque;
import java.util.Deque;
Deque<String> deque = new ArrayDeque<>();
// 在两端添加
deque.addFirst("A");
deque.addLast("B");
deque.offerFirst("C");
deque.offerLast("D");
// 在两端删除
String first = deque.removeFirst();
String last = deque.removeLast();
// 作为栈使用
deque.push("X"); // 压栈
String top = deque.pop(); // 出栈
Map 接口
Map 存储键值对(Key-Value),每个键最多映射到一个值。键不能重复,值可以重复。
HashMap
HashMap 是最常用的 Map 实现类,基于哈希表实现。
底层实现原理(JDK 1.8)
HashMap 采用"数组 + 链表 + 红黑树"的复合结构:
数组(桶 bucket)
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │...│15 │
└─┬─┴───┴─┬─┴───┴───┴───┴───┴───┘
│ │
▼ ▼
链表 红黑树(当链表长度 >= 8 且数组长度 >= 64)
关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
| 初始容量 | 16 | 数组的初始大小 |
| 负载因子 | 0.75 | 扩容阈值 = 容量 × 负载因子 |
| 树化阈值 | 8 | 链表转红黑树的阈值 |
| 树退化阈值 | 6 | 红黑树转链表的阈值 |
哈希计算:
// JDK 1.8 的哈希扰动
static final int hash(Object key) {
int h;
// 高 16 位和低 16 位异或,减少哈希冲突
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
// 索引计算
// index = hash & (n - 1),n 是数组长度(必须是 2 的幂)
扩容机制:
当元素数量超过 容量 × 负载因子 时触发扩容:
- 容量扩大为原来的 2 倍
- 重新计算所有元素的位置
- 元素要么在原位置,要么在原位置 + 原容量的位置
import java.util.HashMap;
import java.util.Map;
// 指定初始容量和负载因子
Map<String, Integer> map = new HashMap<>(16, 0.75f);
// 添加/修改
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Orange", 3);
map.put("Apple", 5); // 会覆盖原来的值
// 访问
int value = map.get("Apple"); // 5
int defaultValue = map.getOrDefault("Grape", 0); // 0
// 检查
boolean hasKey = map.containsKey("Apple"); // true
boolean hasValue = map.containsValue(5); // true
// 删除
map.remove("Banana");
// 遍历方式
// 方式1:遍历键
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
// 方式2:遍历键值对(推荐)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 方式3:遍历值
for (Integer val : map.values()) {
System.out.println(val);
}
// 方式4:forEach(Java 8+)
map.forEach((key, val) -> System.out.println(key + ": " + val));
Java 8 新增方法
Map<String, Integer> map = new HashMap<>();
// putIfAbsent:不存在才添加
map.putIfAbsent("Apple", 1);
// computeIfAbsent:不存在则计算并添加
map.computeIfAbsent("Banana", k -> k.length()); // "Banana".length() = 6
// computeIfPresent:存在则计算并更新
map.computeIfPresent("Apple", (k, v) -> v + 1);
// merge:合并值
map.merge("Apple", 1, Integer::sum); // 如果存在则相加,不存在则设为 1
// getOrDefault:获取值或默认值
int value = map.getOrDefault("Grape", 0);
LinkedHashMap
LinkedHashMap 继承自 HashMap,维护键值对的插入顺序或访问顺序。
import java.util.LinkedHashMap;
// 插入顺序(默认)
LinkedHashMap<String, Integer> linkedMap = new LinkedHashMap<>();
linkedMap.put("A", 1);
linkedMap.put("B", 2);
linkedMap.put("C", 3);
// 遍历顺序:A, B, C
// 访问顺序(可用于实现 LRU 缓存)
LinkedHashMap<String, Integer> lruMap = new LinkedHashMap<>(16, 0.75f, true);
lruMap.put("A", 1);
lruMap.put("B", 2);
lruMap.get("A"); // 访问 A
// 遍历顺序:B, A(最近访问的在后面)
TreeMap
TreeMap 基于红黑树实现,会自动按键排序。
import java.util.TreeMap;
import java.util.Map;
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Banana", 2);
treeMap.put("Apple", 1);
treeMap.put("Orange", 3);
// 遍历顺序:Apple, Banana, Orange(按键自然顺序)
// 特有方法
TreeMap<String, Integer> tree = new TreeMap<>();
tree.put("a", 1);
tree.put("c", 3);
tree.put("e", 5);
tree.put("g", 7);
tree.firstKey(); // "a"
tree.lastKey(); // "g"
tree.lowerKey("e"); // "c"(小于 e 的最大 key)
tree.higherKey("e"); // "g"(大于 e 的最小 key)
tree.subMap("c", "g"); // {c=3, e=5}(范围视图)
ConcurrentHashMap
ConcurrentHashMap 是线程安全的 HashMap,采用分段锁或 CAS 机制实现高并发。
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
// 线程安全的操作
concurrentMap.put("A", 1);
concurrentMap.putIfAbsent("B", 2);
// 原子操作
concurrentMap.compute("A", (k, v) -> v == null ? 1 : v + 1);
Map 常用方法
| 方法 | 说明 |
|---|---|
put(K key, V value) | 添加键值对 |
get(Object key) | 获取值 |
getOrDefault(K key, V defaultValue) | 获取值,不存在返回默认值 |
remove(Object key) | 删除键值对 |
containsKey(Object key) | 判断是否包含键 |
containsValue(Object value) | 判断是否包含值 |
keySet() | 获取所有键的集合 |
values() | 获取所有值的集合 |
entrySet() | 获取所有键值对的集合 |
size() | 返回键值对数量 |
isEmpty() | 判断是否为空 |
clear() | 清空所有元素 |
迭代器
迭代器提供了一种统一的方式来遍历集合。
Iterator
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// 使用 Iterator
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("B".equals(item)) {
iterator.remove(); // 安全删除
}
}
ListIterator
ListIterator 支持双向遍历和修改:
import java.util.ListIterator;
ListIterator<String> listIterator = list.listIterator();
// 正向遍历
while (listIterator.hasNext()) {
System.out.println(listIterator.next());
}
// 反向遍历
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
// 添加元素
listIterator.add("D");
// 设置元素
listIterator.set("E");
fail-fast 机制
Java 集合的迭代器具有 fail-fast 机制:如果在迭代过程中集合被修改(非迭代器自身的 remove/add 方法),会抛出 ConcurrentModificationException。
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
// 错误示例:迭代过程中直接修改集合
for (String item : list) {
if ("B".equals(item)) {
list.remove(item); // ConcurrentModificationException
}
}
// 正确方式:使用迭代器的 remove 方法
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("B".equals(it.next())) {
it.remove(); // 正确
}
}
Collections 工具类
Collections 提供了一些静态方法来操作集合。
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
// 排序
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2));
Collections.sort(list); // [1, 2, 3]
// 反转
Collections.reverse(list); // [3, 2, 1]
// 查找(需先排序)
int index = Collections.binarySearch(list, 2);
// 填充
Collections.fill(list, 0); // [0, 0, 0]
// 交换
Collections.swap(list, 0, 2);
// 最大/最小
int max = Collections.max(list);
int min = Collections.min(list);
// 打乱顺序
Collections.shuffle(list);
// 不可变集合
List<String> immutableList = Collections.unmodifiableList(list);
// 同步集合(线程安全)
List<String> synchronizedList = Collections.synchronizedList(list);
// 空集合(不可变)
List<String> emptyList = Collections.emptyList();
Comparable 和 Comparator
Comparable
Comparable 是内部比较器,类实现该接口后可以自然排序:
class Student implements Comparable<Student> {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
return Integer.compare(this.score, other.score); // 升序
}
}
List<Student> students = new ArrayList<>();
students.add(new Student("张三", 85));
students.add(new Student("李四", 92));
Collections.sort(students); // 按分数升序
Comparator
Comparator 是外部比较器,可以定义多种排序规则:
import java.util.Comparator;
List<Student> students = new ArrayList<>();
students.add(new Student("张三", 85));
students.add(new Student("李四", 92));
students.add(new Student("王五", 85));
// 按分数降序
students.sort(Comparator.comparingInt(s -> s.score).reversed());
// 多字段排序:先按分数降序,再按姓名升序
students.sort(Comparator
.comparingInt((Student s) -> s.score).reversed()
.thenComparing(s -> s.name));
// 自定义比较器
Comparator<Student> comparator = (s1, s2) -> {
int scoreCompare = Integer.compare(s2.score, s1.score);
if (scoreCompare != 0) return scoreCompare;
return s1.name.compareTo(s2.name);
};
students.sort(comparator);
Stream API(Java 8+)
Java 8 引入了 Stream API,可以对集合进行函数式操作。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 过滤
List<Integer> even = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 映射
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// 排序
List<Integer> sorted = numbers.stream()
.sorted()
.collect(Collectors.toList());
// 聚合
int sum = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
double avg = numbers.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0);
// 分组
Map<String, List<Integer>> grouped = numbers.stream()
.collect(Collectors.groupingBy(n -> n % 2 == 0 ? "偶数" : "奇数"));
// 查找
Integer first = numbers.stream()
.findFirst()
.orElse(0);
boolean anyMatch = numbers.stream()
.anyMatch(n -> n > 3);
// 并行流
long count = numbers.parallelStream()
.filter(n -> n > 2)
.count();
选择合适的集合类型
List 选择
| 场景 | 推荐 |
|---|---|
| 随机访问频繁 | ArrayList |
| 尾部增删频繁 | ArrayList |
| 头部增删频繁 | LinkedList |
| 线程安全 | CopyOnWriteArrayList |
Set 选择
| 场景 | 推荐 |
|---|---|
| 只需要去重 | HashSet |
| 需要保持插入顺序 | LinkedHashSet |
| 需要排序 | TreeSet |
Map 选择
| 场景 | 推荐 |
|---|---|
| 通用键值存储 | HashMap |
| 需要保持顺序 | LinkedHashMap |
| 需要按键排序 | TreeMap |
| 高并发环境 | ConcurrentHashMap |
小结
本章我们详细学习了 Java 集合框架的核心内容:
- List 接口:ArrayList、LinkedList、Vector 的底层实现和使用场景
- Set 接口:HashSet、LinkedHashSet、TreeSet 的特点和选择
- Queue 接口:PriorityQueue、ArrayDeque 的使用
- Map 接口:HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap 的底层原理
- 迭代器:遍历和操作集合的统一方式,fail-fast 机制
- Collections 工具类:集合操作的辅助方法
- Comparable 和 Comparator:排序的两种方式
- Stream API:函数式编程风格的数据处理
练习
- 使用 ArrayList 实现 LRU 缓存
- 使用 TreeSet 实现一个排行榜系统
- 使用 HashMap 统计一篇文章中单词出现的频率
- 实现一个线程安全的缓存系统
- 使用 Stream API 处理数据集合