第一部分:Java集合框架概述
理解集合框架的层次结构、核心接口及其应用场景
学习目标
掌握集合框架的设计思想,理解不同集合类型的特点和适用场景
集合框架层次结构
Java集合框架位于java.util
包中,包含两大核心接口:
- Collection接口 - 单列集合的根接口
- Map接口 - 双列集合的根接口
主要接口关系图:
Collection
↓
List
Set
Queue
List接口及其实现
- ArrayList - 基于动态数组,随机访问快
- LinkedList - 基于双向链表,插入删除快
- Vector - 线程安全的动态数组
- Stack - 后进先出(LIFO)的栈结构
List允许重复元素,保留插入顺序
集合类型 | 实现类 | 特点 | 时间复杂度 |
---|---|---|---|
List | ArrayList | 动态数组,快速随机访问 | get/set: O(1) add/remove: O(n) |
List | LinkedList | 双向链表,快速插入删除 | get/set: O(n) add/remove: O(1) |
Set | HashSet | 基于哈希表,无序 | add/remove/contains: O(1) |
Set | TreeSet | 基于红黑树,有序 | add/remove/contains: O(log n) |
Map | HashMap | 键值对,哈希表实现 | get/put: O(1) |
设计思想
Java集合框架采用"接口与实现分离"的设计原则:
- 通过接口定义操作规范
- 提供多种实现满足不同需求
- 使用迭代器统一访问方式
- 支持泛型确保类型安全
第二部分:ArrayList基本使用
掌握ArrayList的创建、初始化及基本操作
学习目标
能够熟练创建ArrayList对象,进行元素添加、访问和删除操作
1
创建ArrayList
Java 7+推荐使用"菱形"语法:
import java.util.ArrayList;
// 创建String类型的ArrayList
ArrayList<String> names = new ArrayList<>();
// 创建Integer类型的ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
// 指定初始容量(可选)
ArrayList<Double> prices = new ArrayList<>(50);
2
添加元素
使用add()方法添加元素:
ArrayList<String> fruits = new ArrayList<>();
// 添加单个元素
fruits.add("Apple");
fruits.add("Banana");
// 在指定位置插入元素
fruits.add(1, "Orange"); // ["Apple", "Orange", "Banana"]
// 添加多个元素
ArrayList<String> moreFruits = new ArrayList<>();
moreFruits.add("Mango");
moreFruits.add("Grape");
fruits.addAll(moreFruits);
3
访问元素
使用get()方法获取元素:
ArrayList<String> colors = new ArrayList<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 获取第一个元素
String first = colors.get(0); // "Red"
// 获取最后一个元素
String last = colors.get(colors.size() - 1); // "Blue"
// 遍历ArrayList
for (int i = 0; i < colors.size(); i++) {
System.out.println(colors.get(i));
}
// 使用增强for循环
for (String color : colors) {
System.out.println(color);
}
4
删除元素
使用remove()方法删除元素:
ArrayList<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
languages.add("JavaScript");
// 按索引删除
languages.remove(1); // 删除"Python"
// 按元素值删除
languages.remove("C++"); // 删除"C++"
// 删除所有元素
languages.clear();
// 删除满足条件的元素
languages.removeIf(lang -> lang.startsWith("J")); // 删除所有以"J"开头的元素
第三部分:ArrayList高级操作
探索ArrayList的搜索、转换、排序等高级功能
学习目标
掌握ArrayList的搜索、排序、转换等高级操作,理解批量操作技巧
1
搜索与检查
ArrayList<Integer> numbers = new ArrayList<>(
Arrays.asList(10, 20, 30, 40, 50));
// 检查元素是否存在
boolean hasTwenty = numbers.contains(20); // true
// 查找元素索引
int index = numbers.indexOf(30); // 2
int lastIndex = numbers.lastIndexOf(10); // 0
// 检查ArrayList是否为空
boolean isEmpty = numbers.isEmpty(); // false
// 获取ArrayList大小
int size = numbers.size(); // 5
2
排序与转换
ArrayList<String> words = new ArrayList<>(
Arrays.asList("banana", "apple", "cherry"));
// 自然排序
Collections.sort(words); // ["apple", "banana", "cherry"]
// 自定义排序
Collections.sort(words, Comparator.reverseOrder());
// 使用Lambda表达式排序
words.sort((a, b) -> a.length() - b.length());
// 转换为数组
String[] wordsArray = words.toArray(new String[0]);
// 转换为不可修改列表
List<String> unmodifiable = Collections.unmodifiableList(words);
3
批量操作
ArrayList<Integer> list1 = new ArrayList<>(
Arrays.asList(1, 2, 3, 4));
ArrayList<Integer> list2 = new ArrayList<>(
Arrays.asList(3, 4, 5, 6));
// 并集
ArrayList<Integer> union = new ArrayList<>(list1);
union.addAll(list2); // [1,2,3,4,3,4,5,6]
// 交集
ArrayList<Integer> intersection = new ArrayList<>(list1);
intersection.retainAll(list2); // [3,4]
// 差集
ArrayList<Integer> difference = new ArrayList<>(list1);
difference.removeAll(list2); // [1,2]
// 子列表
List<Integer> subList = list1.subList(1, 3); // [2,3]
第四部分:ArrayList内部原理
深入理解ArrayList的底层实现与性能特点
学习目标
掌握ArrayList的内部数据结构、扩容机制和性能特征
底层数据结构
ArrayList基于动态数组实现:
- 内部使用
Object[] elementData
数组存储元素 - 默认初始容量为
10
- 维护
size
变量记录实际元素数量 - 数组容量可能大于实际元素数量
ArrayList内部结构
"A"
"B"
"C"
null
null
null
null
null
null
null
size = 3, capacity = 10
扩容机制
当添加元素超过当前容量时触发扩容:
- 新容量 = 旧容量 * 1.5
- 使用Arrays.copyOf()创建新数组
- 复制原数组元素到新数组
- 扩容操作时间复杂度为O(n)
// ArrayList扩容核心代码
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
ArrayList性能特征
第五部分:常见错误与最佳实践
避免常见陷阱,掌握ArrayList高效使用技巧
学习目标
识别并解决使用ArrayList时的常见问题,遵循最佳实践
常见错误
- 索引越界:访问超出size()-1的索引
- 并发修改异常:遍历时修改集合
- 未指定泛型类型:导致类型转换异常
- 频繁中间插入:导致性能下降
- 未初始化直接使用:NullPointerException
并发修改异常示例
ArrayList<String> list = new ArrayList<>(
Arrays.asList("A", "B", "C"));
// 错误:遍历时删除元素
for (String s : list) {
if ("B".equals(s)) {
list.remove(s); // 抛出ConcurrentModificationException
}
}
// 正确做法:使用迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) {
it.remove(); // 安全删除
}
}
最佳实践
- 预分配容量:已知大小时使用带初始容量的构造函数
- 使用isEmpty():代替size()==0检查空列表
- 避免频繁扩容:预估大小并一次性分配足够空间
- 使用增强for循环:简化遍历代码
- 多线程环境:使用Collections.synchronizedList()或CopyOnWriteArrayList
性能优化技巧
// 预分配容量(避免多次扩容)
ArrayList<User> users = new ArrayList<>(10000);
// 批量添加数据
users.addAll(getUsersFromDatabase());
// 使用ensureCapacity()预扩容
users.ensureCapacity(20000);
// 使用trimToSize()释放多余空间
users.trimToSize();
综合练习
- 创建一个Student类,包含id、name和score属性
- 使用ArrayList存储多个Student对象
- 实现按score降序排序
- 查找所有score大于90的学生
- 计算平均分并输出高于平均分的学生