引言:什么是集合?
集合(Collection)是用于存储多个对象的数据结构。与数组不同,集合的大小可以动态增长。
Java集合框架提供了一套完整的接口和类,主要包括:
- List:有序集合,可重复
- Set:无序集合,不可重复
- Map:键值对映射
集合 vs 数组:
| 特性 | 数组 | 集合 |
|---|---|---|
| 大小 | 固定 | 可动态增长 |
| 类型 | 基本类型和对象 | 只能存储对象 |
| 操作 | 需要手动处理 | 提供丰富的方法 |
List接口简介
List是有序的集合(也称为序列),可以精确控制每个元素的位置,可以通过索引访问元素。
List的特点
有序:元素按插入顺序存储
可重复:允许存储相同的元素
索引访问:可以通过索引访问元素
List的主要实现类
| 实现类 | 底层数据结构 | 特点 | 适用场景 |
|---|---|---|---|
| ArrayList | 动态数组 | 查询快,增删慢 | 频繁查询,少量增删 |
| LinkedList | 双向链表 | 增删快,查询慢 | 频繁增删,查询少 |
| Vector | 动态数组 | 线程安全,已过时 | 不推荐使用 |
ArrayList的使用
创建ArrayList
import java.util.ArrayList;
import java.util.List;
// 方式1:创建空列表(推荐)
List list1 = new ArrayList<>();
// 方式2:创建时指定初始容量
List list2 = new ArrayList<>(20);
// 方式3:通过Arrays.asList创建固定列表
List list3 = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
添加元素 - add()
List fruits = new ArrayList<>();
// 添加单个元素
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
// 在指定位置添加元素
fruits.add(1, "Mango"); // 在索引1位置插入
System.out.println(fruits); // [Apple, Mango, Banana, Orange]
访问元素 - get()
List fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
// 通过索引访问
System.out.println(fruits.get(0)); // Apple
System.out.println(fruits.get(1)); // Banana
System.out.println(fruits.get(2)); // Orange
修改元素 - set()
List fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.set(0, "Mango"); // 将索引0的元素改为Mango
System.out.println(fruits); // [Mango, Banana]
删除元素 - remove()
List fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
// 按索引删除
fruits.remove(0); // 删除索引0的元素
// 按对象删除
fruits.remove("Banana"); // 删除元素"Banana"
System.out.println(fruits); // [Orange]
遍历List的几种方式
List fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
// 方式1:普通for循环
System.out.println("===== 普通for循环 =====");
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
}
// 方式2:增强for循环
System.out.println("===== 增强for循环 =====");
for (String fruit : fruits) {
System.out.println(fruit);
}
// 方式3:Iterator迭代器
System.out.println("===== Iterator迭代器 =====");
Iterator iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
// 方式4:Java 8+的forEach
System.out.println("===== forEach方法 =====");
fruits.forEach(fruit -> System.out.println(fruit));
LinkedList的使用
LinkedList是基于双向链表实现的List,适合频繁的增删操作。
创建LinkedList
import java.util.LinkedList;
import java.util.List;
List linkedList = new LinkedList<>();
linkedList.add("First");
linkedList.add("Second");
linkedList.add("Third");
System.out.println(linkedList); // [First, Second, Third]
LinkedList特有的方法
LinkedList list = new LinkedList<>();
// 添加元素(头尾操作)
list.addFirst("First"); // 添加到头部
list.addLast("Last"); // 添加到尾部
list.add("Middle"); // 默认添加到尾部
System.out.println(list); // [First, Middle, Last]
// 获取头尾元素
System.out.println(list.getFirst()); // First
System.out.println(list.getLast()); // Last
// 删除头尾元素
list.removeFirst();
list.removeLast();
System.out.println(list); // [Middle]
ArrayList vs LinkedList对比
ArrayList
底层:动态数组
查询:通过索引直接访问,O(1)
增删:需要移动元素,O(n)
适用:频繁查询场景
LinkedList
底层:双向链表
查询:需要遍历,O(n)
增删:只需修改指针,O(1)
适用:频繁增删场景
性能测试示例
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
int n = 10000;
// ArrayList插入性能
long start = System.currentTimeMillis();
List arrayList = new ArrayList<>();
for (int i = 0; i < n; i++) {
arrayList.add(0, i); // 头部插入
}
System.out.println("ArrayList头部插入耗时: " + (System.currentTimeMillis() - start) + "ms");
// LinkedList插入性能
start = System.currentTimeMillis();
List linkedList = new LinkedList<>();
for (int i = 0; i < n; i++) {
linkedList.add(0, i); // 头部插入
}
System.out.println("LinkedList头部插入耗时: " + (System.currentTimeMillis() - start) + "ms");
List的常用方法汇总
| 方法 | 说明 | 返回值 |
|---|---|---|
| add(E e) | 添加元素到末尾 | boolean |
| add(int index, E e) | 在指定位置插入元素 | void |
| get(int index) | 获取指定位置的元素 | E |
| set(int index, E e) | 修改指定位置的元素 | E(返回原元素) |
| remove(int index) | 删除指定位置的元素 | E(返回被删除的元素) |
| remove(Object o) | 删除第一个匹配的元素 | boolean |
| size() | 返回元素个数 | int |
| isEmpty() | 判断是否为空 | boolean |
| contains(Object o) | 判断是否包含元素 | boolean |
| clear() | 清空所有元素 | void |
| indexOf(Object o) | 返回元素首次出现的索引 | int |
| lastIndexOf(Object o) | 返回元素最后出现的位置 | int |
| subList(int from, int to) | 返回子列表 | List |
实战练习
练习1:学生成绩管理系统
import java.util.ArrayList;
import java.util.List;
class Student {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() { return name; }
public int getScore() { return score; }
@Override
public String toString() {
return name + ": " + score;
}
}
public class StudentManager {
public static void main(String[] args) {
List students = new ArrayList<>();
students.add(new Student("张三", 85));
students.add(new Student("李四", 92));
students.add(new Student("王五", 78));
System.out.println("===== 学生成绩列表 =====");
for (Student s : students) {
System.out.println(s);
}
System.out.println("\\n===== 统计成绩 =====");
int total = 0;
for (Student s : students) {
total += s.getScore();
}
System.out.println("平均分: " + (double) total / students.size());
}
}
小结
- List是有序、可重复的集合,可以通过索引访问
- ArrayList基于动态数组,查询快、增删慢
- LinkedList基于双向链表,增删快、查询慢
- 遍历方式:普通for、增强for、Iterator、forEach
- 根据实际场景选择合适的List实现类
☕ Java 在线代码编辑器
📝 运行结果