Java-day13
引入
Java 集合框架是处理"批量数据"的核心工具,其中 List 体系以"有序、可重复"的特性,成为日常开发中最常用的集合类型。本文将围绕 List 接口的两大实现类 `ArrayList` 和 `LinkedList`,以及遗留类 `Vector` 展开,从底层数据结构、核心方法到适用场景,全面解析 List 集合的设计逻辑与实战技巧,帮助读者掌握"何时用何集合"的选型能力。
一、Java 集合框架概述
Java 集合框架主要分为四大体系:
Set:无序、不可重复的集合;
List:有序、可重复的集合(本文核心);
Map:具有键值映射关系的集合;
Queue:队列式集合(先进先出)。
其中,List 是 Collection 接口的子接口,它保证元素"按插入顺序排序",支持通过索引直接操作元素,且允许元素重复。
二、ArrayList 集合:基于动态数组的 List 实现
2.1 ArrayList 底层原理与特点
-
**数据结构**:内部封装了一个 `Object[]` 类型的**动态数组**,初始长度为 10,当数组容量不足时会**扩容(默认扩容为原容量的 1.5 倍)**;
-
**核心特点**:
-
查询快(基于数组的索引随机访问),增删慢(增删元素需移动数组元素);
-
线程不安全,执行效率高;
-
元素类型为 `Object`,支持向上转型(如存储 `Cat`、`Dog` 等子类对象,体现多态)。
2.2 ArrayList 核心方法与实战
```java
java
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
// 创建 ArrayList 集合(泛型指定为 String)
ArrayList<String> list = new ArrayList<>();
// 1. 添加元素:add()
list.add("青城");
list.add("博雅");
System.out.println("添加元素后:" + list); // 输出:[青城, 博雅]
// 2. 在指定位置插入元素:add(int index, Object element)
list.add(1, "教育");
System.out.println("指定位置插入后:" + list); // 输出:[青城, 教育, 博雅]
// 3. 获取元素数量:size()
System.out.println("元素数量:" + list.size()); // 输出:3
// 4. 获取指定索引元素:get(int index)
System.out.println("索引1的元素:" + list.get(1)); // 输出:教育
// 5. 修改元素:set(int index, Object element)
list.set(1, "QC");
System.out.println("修改元素后:" + list); // 输出:[青城, QC, 博雅]
// 6. 删除指定索引元素:remove(int index)
list.remove(2);
System.out.println("删除索引2后:" + list); // 输出:[青城, QC]
// 7. 删除指定元素:remove(Object element)
list.remove("青城");
System.out.println("删除元素'青城'后:" + list); // 输出:[QC]
// 8. 清空集合:clear()
list.clear();
System.out.println("清空后是否为空:" + list.isEmpty()); // 输出:true
// 9. 遍历集合(三种方式)
list.add("A");
list.add("B");
list.add("C");
// 方式1:for 循环 + 索引
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " "); // 输出:A B C
}
System.out.println();
// 方式2:增强 for 循环
for (String s : list) {
System.out.print(s + " "); // 输出:A B C
}
System.out.println();
// 方式3:迭代器
java.util.Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " "); // 输出:A B C
}
}
}
```
2.3 ArrayList 适用场景
-
适合**查询操作频繁**、**增删操作较少**的场景(如数据展示、报表导出);
-
不适合多线程环境(需手动加锁或改用 `Vector`)。
三、LinkedList 集合:基于双向链表的 List 实现
3.1 LinkedList 底层原理与特点
-
**数据结构**:内部封装了一个**双向链表**,每个节点包含"前驱节点引用""元素值""后继节点引用";
-
**核心特点**:
-
增删快(只需修改节点的引用指向),查询慢(需从链表头/尾遍历);
-
线程不安全;
-
除了 List 接口的方法,还提供了**操作链表头尾**的特有方法(如 `addFirst()`、`getLast()` 等)。
3.2 LinkedList 核心方法与实战
```java
java
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
// 创建 LinkedList 集合(泛型指定为 Integer)
LinkedList<Integer> list = new LinkedList<>();
// 1. 添加元素:add()、addFirst()、addLast()
list.add(1);
list.add(2);
list.addFirst(0);
list.addLast(3);
System.out.println("添加元素后:" + list); // 输出:[0, 1, 2, 3]
// 2. 在指定位置插入元素:add(int index, Object element)
list.add(2, 9);
System.out.println("指定位置插入后:" + list); // 输出:[0, 1, 9, 2, 3]
// 3. 获取元素:get(int index)、getFirst()、getLast()
System.out.println("索引2的元素:" + list.get(2)); // 输出:9
System.out.println("第一个元素:" + list.getFirst()); // 输出:0
System.out.println("最后一个元素:" + list.getLast()); // 输出:3
// 4. 修改元素:set(int index, Object element)
list.set(2, 8);
System.out.println("修改元素后:" + list); // 输出:[0, 1, 8, 2, 3]
// 5. 删除元素:remove()、remove(int index)、removeFirst()、removeLast()
list.remove(); // 删除第一个元素
list.remove(2); // 删除索引2的元素
System.out.println("删除后:" + list); // 输出:[1, 8, 3]
// 6. 清空集合:clear()
list.clear();
System.out.println("清空后是否为空:" + list.isEmpty()); // 输出:true
}
}
```
3.3 LinkedList 适用场景
-
适合**增删操作频繁**、**查询操作较少**的场景(如消息队列、历史记录);
-
利用其"链表头尾操作"的特性,可作为**栈(Stack)**或**队列(Queue)**的实现。
四、Vector 集合:遗留的线程安全 List 实现
4.1 Vector 底层原理与特点
-
**数据结构**:基于**数组**实现,与 `ArrayList` 类似;
-
**核心特点**:
-
线程安全(所有方法加了 `synchronized` 同步锁),执行效率低;
-
扩容机制为"原容量的 2 倍"(`ArrayList` 是 1.5 倍);
-
属于 Java 早期遗留类,**不建议在新代码中使用**(可改用 `ArrayList` 加手动锁,或使用 `ConcurrentArrayList`)。
4.2 Vector 核心方法示例
```java
java
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
// 创建 Vector 集合
Vector<String> vector = new Vector<>();
// 添加元素
vector.add("Apple");
vector.addElement("Banana"); // 与 add() 功能类似,为遗留方法
System.out.println("添加后:" + vector); // 输出:[Apple, Banana]
// 访问元素
System.out.println("索引1的元素:" + vector.get(1)); // 输出:Banana
System.out.println("索引1的元素(遗留方法):" + vector.elementAt(1)); // 输出:Banana
// 修改元素
vector.set(1, "Cherry");
System.out.println("修改后:" + vector); // 输出:[Apple, Cherry]
// 删除元素
vector.remove(1);
vector.removeElement("Apple");
System.out.println("删除后:" + vector); // 输出:[]
}
}
```
五、List 集合选型与对比
| 集合类 | 底层结构 | 线程安全 | 查询效率 | 增删效率 | 适用场景 |
|---|---|---|---|---|---|
| ArrayList | 动态数组 | 不安全 | 高 | 低 | 查询多、增删少的场景 |
| LinkedList | 双向链表 | 不安全 | 低 | 高 | 增删多、查询少的场景 |
| Vector | 动态数组 | 安全 | 高 | 低 | 遗留系统维护、多线程(不推荐) |
六、总结:List 集合的核心要点
- ArrayList:
-
基于动态数组,查询快、增删慢,线程不安全;
-
掌握 `add()`、`get()`、`set()`、`remove()` 等核心方法,以及三种遍历方式。
- LinkedList:
-
基于双向链表,增删快、查询慢,线程不安全;
-
除 List 通用方法外,还需掌握 `addFirst()`、`getLast()` 等链表头尾操作方法。
- Vector:
- 线程安全但效率低,属于遗留类,新代码中尽量避免使用。
- 选型建议:
-
优先考虑 `ArrayList`(性能优、使用广泛);
-
增删频繁场景选 `LinkedList`;
-
多线程场景需结合锁机制或改用并发集合(如 `CopyOnWriteArrayList`)。
通过本文的学习,相信你已对 Java List 集合的实现类有了全面理解。在实际开发中,需根据"查询/增删频率""线程安全需求"等因素选择合适的集合,以达到最优性能。后续文章将解析 Set、Map 等其他集合体系,敬请关注。