Java List 接口知识点详解

一、List 接口概述

1. 基本定义

  • 继承关系List 是 Java 集合框架(Collection Framework)中的一个有序队列接口,直接继承自 Collection 接口。
  • 核心特性
    • 有序性:元素按插入顺序存储,可通过索引(Index)访问元素。
    • 可重复性:允许存储重复元素。
    • 动态扩容:底层实现类(如 ArrayListLinkedList)支持动态调整容量。

2. 与其他接口的区别

接口有序性重复性数据结构典型实现类
List线性表ArrayListLinkedList
Set集合(哈希表等)HashSetTreeSet
Queue队列(FIFO)LinkedListPriorityQueue

二、List 接口核心方法

1. 元素操作方法

(1)添加元素
  • boolean add(E e):向列表末尾添加元素,成功返回 true
List<String> list = new ArrayList<>();
list.add("Apple"); // 添加到末尾

void add(int index, E element):在指定索引处插入元素,后续元素后移。

list.add(1, "Banana"); // 在索引1处插入元素
(2)删除元素
  • E remove(int index):移除指定索引处的元素,返回被删除元素。
String removed = list.remove(0); // 移除索引0的元素

boolean remove(Object o):移除列表中第一个匹配的元素(通过 equals 方法判断)。

list.remove("Apple"); // 移除值为"Apple"的元素
(3)修改元素
  • E set(int index, E element):用指定元素替换指定索引处的元素,返回旧元素。
String oldValue = list.set(0, "Grape"); // 将索引0的元素改为"Grape"
(4)查询元素
  • E get(int index):返回指定索引处的元素。
String first = list.get(0); // 获取索引0的元素

int indexOf(Object o):返回元素首次出现的索引,不存在则返回 -1

int pos = list.indexOf("Banana"); // 查询"Banana"的位置
  • int lastIndexOf(Object o):返回元素最后一次出现的索引,不存在则返回 -1

2. 集合操作方法

  • boolean contains(Object o):判断列表是否包含指定元素(基于 equals)。
  • boolean.addAll(Collection<? extends E> c):将其他集合的所有元素添加到列表末尾。
  • void clear():移除列表中的所有元素。
  • boolean isEmpty():判断列表是否为空。
  • int size():返回列表中的元素个数。

3. 迭代与视图方法

  • 迭代器(Iterator)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String element = it.next();
    // 处理元素
}

列表迭代器(ListIterator):支持双向遍历和元素修改:

ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
    String element = lit.next();
    lit.set(element + "_modified"); // 修改元素
}
  • 子列表(SubList):返回列表中指定范围的视图(List.subList(int fromIndex, int toIndex)):
List<String> sub = list.subList(0, 2); // 包含索引0,不包含索引2

三、List 接口的实现类

1. ArrayList

(1)特点
  • 底层结构:动态数组(Object[])。
  • 优缺点
    • ✅ 随机访问(get(int))速度快(时间复杂度 O (1))。
    • ❌ 插入 / 删除元素时需移动后续元素,效率较低(时间复杂度 O (n))。
  • 适用场景:频繁查询、较少增删的场景(如数据展示、日志记录)。
(2)扩容机制
  • 初始容量默认值为 10(JDK 1.8)。
  • 当元素数量超过容量时,新容量为 原容量的 1.5 倍(通过 Arrays.copyOf 复制数组)。

2. LinkedList

(1)特点
  • 底层结构:双向链表(每个节点包含 prevnext 指针)。
  • 优缺点
    • ✅ 插入 / 删除元素时只需修改指针,效率高(时间复杂度 O (1),若已知节点位置)。
    • ❌ 随机访问需遍历链表,效率低(时间复杂度 O (n))。
  • 适用场景:频繁增删的场景(如队列、栈、缓存)。
(2)特殊方法
  • 可作为队列(Queue)使用:
LinkedList<String> queue = new LinkedList<>();
queue.offer("A"); // 入队(添加到末尾)
String first = queue.poll(); // 出队(移除并返回头部元素)

可作为栈(Stack)使用:

queue.push("B"); // 入栈(添加到头部)
String last = queue.pop(); // 出栈(移除并返回头部元素)

3. Vector(线程安全)

(1)特点
  • 底层结构:动态数组,与 ArrayList 类似。
  • 线程安全:方法通过 synchronized 修饰(如 add()get()),但性能较低。
  • 适用场景:多线程环境下需要线程安全的场景(较冷门,推荐使用 Collections.synchronizedList() 替代)。

4. 实现类对比表

实现类底层结构线程安全随机访问效率增删效率(中间位置)默认初始容量
ArrayList动态数组高(O (1))低(O (n))10
LinkedList双向链表低(O (n))高(O (1))-
Vector动态数组高(O (1))低(O (n))10

四、List 接口的常用操作场景

1. 遍历列表的 4 种方式

(1)普通 for 循环(索引遍历)
for (int i = 0; i < list.size(); i++) {
    String element = list.get(i);
}

适用场景:需要通过索引操作元素(如修改、删除)。

(2)增强 for 循环(foreach)
for (String element : list) {
    // 只读操作元素
}

注意:遍历时若修改列表(如 list.remove()),会抛出 ConcurrentModificationException(fail-fast 机制)。

(3)Iterator 迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String element = it.next();
    if (element.equals("Apple")) {
        it.remove(); // 安全删除元素的方式
    }
}

优势:支持遍历过程中安全删除元素(通过 Iterator.remove())。

(4)Java 8 Stream 流式遍历
list.stream().forEach(element -> {
    System.out.println(element);
});

适用场景:结合 Lambda 表达式实现复杂逻辑(如过滤、映射)。

2. 列表排序与搜索

(1)排序(Collections.sort()
List<Integer> nums = Arrays.asList(3, 1, 4, 2);
Collections.sort(nums); // 升序排列(默认自然排序)
// 自定义排序(降序)
Collections.sort(nums, (a, b) -> b - a);
(2)二分查找(Collections.binarySearch()
Collections.sort(nums); // 需先排序
int index = Collections.binarySearch(nums, 3); // 返回元素3的索引

3. 线程安全处理

  • 场景:多线程环境下操作 List 时,需保证线程安全。
  • 解决方案
    1. 使用 Vector(性能较低)。
    2. 通过 Collections.synchronizedList() 包装普通 List
List<String> safeList = Collections.synchronizedList(new ArrayList<>());

使用并发包 java.util.concurrent 中的 CopyOnWriteArrayList(适用于读多写少场景):

List<String> concurrentList = new CopyOnWriteArrayList<>();

五、常见问题与最佳实践

1. ArrayList vs LinkedList 如何选择?

  • 优先选 ArrayList:需要频繁随机访问(如查询),或数据量已知、增删操作少。
  • 优先选 LinkedList:需要频繁在头部 / 中间插入 / 删除元素,或数据量不确定、需高效动态调整。

2. 列表扩容的性能影响

  • ArrayList 扩容时会创建新数组并复制旧元素,若初始容量预估不足,多次扩容会导致性能下降。
  • 最佳实践:通过构造方法指定初始容量:
    List<String> list = new ArrayList<>(100); // 初始容量设为100,减少扩容次数

    3. 避免内存泄漏

  • 若存储大量对象,需及时调用 clear() 或置为 null,帮助垃圾回收器回收内存。
  • 强制类型转换风险:非泛型 List 会存储 Object 类型,取出时需强制类型转换,可能引发 ClassCastException
  • 最佳实践:使用泛型限定元素类型:
List<String> list = new ArrayList<>(); // 限定只能存储String类型

六、总结

特性List 接口特点
核心优势有序性、可重复性、索引访问,适用于需要按顺序操作的数据场景。
实现类选择- 高频查询:ArrayList
- 高频增删:LinkedList
- 线程安全:CopyOnWriteArrayList
常用操作添加 / 删除元素、遍历、排序、子列表操作、线程安全处理。

通过掌握 List 接口的核心方法与实现类特性,可在开发中高效处理线性数据集合,提升代码的健壮性与性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值