第一部分: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性能特征

  • 快速随机访问:通过索引访问元素时间复杂度为O(1)
  • 尾部添加高效:平均时间复杂度O(1),扩容时O(n)
  • 中间插入/删除慢:需要移动元素,时间复杂度O(n)
  • 内存占用少:相比LinkedList,每个元素占用更少内存
  • 非线程安全:多线程环境下需要外部同步
  • 第五部分:常见错误与最佳实践

    避免常见陷阱,掌握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();

    综合练习

    1. 创建一个Student类,包含id、name和score属性
    2. 使用ArrayList存储多个Student对象
    3. 实现按score降序排序
    4. 查找所有score大于90的学生
    5. 计算平均分并输出高于平均分的学生