Java 中的 List 接口实现类

1. List 接口实现类概览

List (接口)
├── ArrayList          - 最常用的实现,基于动态数组
├── LinkedList         - 基于双向链表
├── Vector             - 线程安全的动态数组(已过时)
├── Stack              - 继承自 Vector,栈实现(已过时)
├── CopyOnWriteArrayList - 写时复制的线程安全列表
├── AbstractList       - 抽象类,提供部分实现
├── AbstractSequentialList - 抽象类,为顺序访问优化
├── Arrays.asList()    - 返回固定大小的列表
├── Collections.emptyList() - 空列表
├── Collections.unmodifiableList() - 不可变列表
├── Collections.synchronizedList() - 同步列表
└── 第三方实现
    ├── FastList (Eclipse Collections)
    ├── TreeList (Apache Commons Collections)
    └── GapList (Koloboke)

2. 核心实现类详解

2.1 ArrayList

import java.util.*;

public class ArrayListExample {
    public static void main(String[] args) {
        // 创建 ArrayList
        List<String> list = new ArrayList<>();
        
        // 指定初始容量
        List<Integer> numbers = new ArrayList<>(100);
        
        // 从其他集合创建
        List<String> copy = new ArrayList<>(list);
        
        // 添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Orange");
        
        // 在指定位置插入
        list.add(1, "Grape");
        
        // 批量添加
        List<String> fruits = Arrays.asList("Mango", "Peach");
        list.addAll(fruits);
        
        // 访问元素
        String first = list.get(0);
        
        // 修改元素
        list.set(0, "Cherry");
        
        // 删除元素
        list.remove("Banana");      // 按值删除
        list.remove(0);             // 按索引删除
        
        // 查找元素
        boolean contains = list.contains("Apple");
        int index = list.indexOf("Orange");
        
        // 获取大小
        int size = list.size();
        
        // 判断是否为空
        boolean empty = list.isEmpty();
        
        // 转换为数组
        String[] array = list.toArray(new String[0]);
        
        // 清空列表
        list.clear();
        
        // 遍历方式
        // 1. for 循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        
        // 2. for-each
        for (String item : list) {
            System.out.println(item);
        }
        
        // 3. Iterator
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        
        // 4. ListIterator(双向遍历)
        ListIterator<String> listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            System.out.println(listIterator.next());
        }
        
        // 5. Stream API (Java 8+)
        list.stream().forEach(System.out::println);
    }
}

特点:

  • 基于动态数组实现
  • 随机访问快 O(1)
  • 插入删除慢 O(n)
  • 非线程安全
  • 允许 null 元素
  • 允许重复元素

适用场景:

  • 频繁随机访问
  • 尾部插入删除
  • 数据量可预估

2.2 LinkedList

import java.util.*;

public class LinkedListExample {
    public static void main(String[] args) {
        // 创建 LinkedList
        LinkedList<String> list = new LinkedList<>();
        
        // 添加元素
        list.add("A");
        list.add("B");
        list.add("C");
        
        // 头部添加
        list.addFirst("Start");
        
        // 尾部添加
        list.addLast("End");
        
        // 在指定位置插入
        list.add(2, "Middle");
        
        // 获取首尾元素
        String first = list.getFirst();
        String last = list.getLast();
        
        // 删除首尾元素
        list.removeFirst();
        list.removeLast();
        
        // 作为栈使用
        list.push("Top");        // 压栈
        String top = list.pop(); // 弹栈
        String peek = list.peek(); // 查看栈顶
        
        // 作为队列使用
        list.offer("QueueItem"); // 入队
        String queueItem = list.poll(); // 出队
        String queuePeek = list.peek(); // 查看队首
        
        // 双向遍历
        ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()) {
            System.out.println("Next: " + iterator.next());
        }
        while (iterator.hasPrevious()) {
            System.out.println("Previous: " + iterator.previous());
        }
        
        // 转换为数组
        String[] array = list.toArray(new String[0]);
    }
}

特点:

  • 基于双向链表实现
  • 随机访问慢 O(n)
  • 插入删除快 O(1)
  • 非线程安全
  • 允许 null 元素
  • 允许重复元素
  • 可作为栈、队列、双端队列使用

适用场景:

  • 频繁插入删除
  • 头部/尾部操作
  • 实现栈/队列

2.3 Vector

import java.util.Vector;

public class VectorExample {
    public static void main(String[] args) {
        // 创建 Vector
        Vector<String> vector = new Vector<>();
        
        // 指定初始容量和容量增量
        Vector<Integer> numbers = new Vector<>(100, 50);
        
        // 添加元素(所有方法都是同步的)
        vector.add("A");
        vector.add("B");
        
        // 访问元素
        String element = vector.get(0);
        
        // Vector 特有的方法
        vector.addElement("C");           // 等同于 add()
        String firstElement = vector.firstElement();
        String lastElement = vector.lastElement();
        
        // 容量相关
        int capacity = vector.capacity();
        vector.ensureCapacity(200);       // 确保最小容量
        vector.trimToSize();              // 调整容量到实际大小
        
        // 复制到数组
        String[] array = new String[vector.size()];
        vector.copyInto(array);
    }
}

特点:

  • 线程安全(所有方法都同步)
  • 基于动态数组
  • 性能较差(同步开销)
  • 已过时,不推荐使用
  • 允许 null 元素

适用场景:

  • 需要线程安全的旧代码
  • 不推荐新项目使用

2.4 Stack

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        // 创建 Stack
        Stack<String> stack = new Stack<>();
        
        // 压栈
        stack.push("First");
        stack.push("Second");
        stack.push("Third");
        
        // 查看栈顶元素
        String top = stack.peek(); // "Third"
        
        // 弹栈
        String popped = stack.pop(); // "Third"
        
        // 搜索元素(从栈顶开始,返回位置)
        int position = stack.search("Second"); // 1
        
        // 判断是否为空
        boolean empty = stack.empty();
        
        // Stack 继承自 Vector,也有 Vector 的方法
        int size = stack.size();
    }
}

特点:

  • 继承自 Vector
  • 后进先出(LIFO)
  • 线程安全
  • 已过时,推荐使用 ArrayDeque
  • 允许 null 元素

适用场景:

  • 需要栈结构的旧代码
  • 不推荐新项目使用

2.5 CopyOnWriteArrayList

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Iterator;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        // 创建 CopyOnWriteArrayList
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        
        // 添加元素
        list.add("A");
        list.add("B");
        list.add("C");
        
        // 批量添加
        list.addAll(Arrays.asList("D", "E", "F"));
        
        // 读操作(无锁)
        String element = list.get(0);
        boolean contains = list.contains("B");
        int size = list.size();
        
        // 写操作(会创建新数组)
        list.add("G");
        list.remove("A");
        list.set(0, "NewB");
        
        // 迭代器(弱一致性)
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            // 迭代期间可以安全修改列表
            list.add("H"); // 不会影响当前迭代
        }
        
        // 并发场景示例
        Runnable reader = () -> {
            for (String item : list) {
                System.out.println("Reading: " + item);
            }
        };
        
        Runnable writer = () -> {
            list.add("New Item");
            System.out.println("Added new item");
        };
        
        // 多个线程可以同时读取
        new Thread(reader).start();
        new Thread(reader).start();
        
        // 写操作会创建新副本,不影响正在进行的读操作
        new Thread(writer).start();
    }
}

特点:

  • 写时复制策略
  • 线程安全
  • 读操作无锁,性能高
  • 写操作需要复制数组,成本高
  • 迭代器弱一致性,不会抛出 ConcurrentModificationException
  • 允许 null 元素

适用场景:

  • 读多写少的并发场景
  • 事件监听器列表
  • 配置信息列表

3. 工具类创建的 List

3.1 Arrays.asList()

import java.util.*;

public class ArraysAsListExample {
    public static void main(String[] args) {
        // 创建固定大小的列表
        List<String> list = Arrays.asList("A", "B", "C");
        
        // 从数组创建
        String[] array = {"X", "Y", "Z"};
        List<String> listFromArray = Arrays.asList(array);
        
        // 访问元素
        String element = list.get(0);
        
        // 遍历
        for (String item : list) {
            System.out.println(item);
        }
        
        // ⚠️ 注意:不能添加或删除元素
        // list.add("D"); // 抛出 UnsupportedOperationException
        // list.remove(0); // 抛出 UnsupportedOperationException
        
        // 可以修改元素
        list.set(0, "NewA");
        
        // 修改数组会影响列表
        array[0] = "NewX";
        System.out.println(listFromArray.get(0)); // "NewX"
        
        // 修改列表会影响数组
        listFromArray.set(1, "NewY");
        System.out.println(array[1]); // "NewY"
        
        // 创建可修改的列表
        List<String> modifiableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
        modifiableList.add("D"); // 可以添加
    }
}

3.2 Collections 工具方法

import java.util.*;

public class CollectionsListExample {
    public static void main(String[] args) {
        // 空列表(不可变)
        List<String> emptyList = Collections.emptyList();
        // emptyList.add("A"); // 抛出 UnsupportedOperationException
        
        // 单元素列表(不可变)
        List<String> singletonList = Collections.singletonList("OnlyOne");
        // singletonList.add("B"); // 抛出 UnsupportedOperationException
        
        // 不可变列表
        List<String> original = Arrays.asList("A", "B", "C");
        List<String> unmodifiableList = Collections.unmodifiableList(original);
        // unmodifiableList.add("D"); // 抛出 UnsupportedOperationException
        
        // 同步列表(线程安全)
        List<String> syncList = Collections.synchronizedList(new ArrayList<>());
        syncList.add("A");
        syncList.add("B");
        
        // 迭代时需要手动同步
        synchronized (syncList) {
            for (String item : syncList) {
                System.out.println(item);
            }
        }
        
        // checkedList(类型安全)
        List rawList = new ArrayList();
        List<String> checkedList = Collections.checkedList(rawList, String.class);
        // checkedList.add(123); // 编译通过,运行时抛出 ClassCastException
        
        // nCopies(创建包含 n 个相同元素的列表)
        List<String> repeatedList = Collections.nCopies(5, "Repeat");
        System.out.println(repeatedList); // [Repeat, Repeat, Repeat, Repeat, Repeat]
    }
}

4. List.of() (Java 9+)

import java.util.List;

public class ListOfExample {
    public static void main(String[] args) {
        // 创建不可变列表
        List<String> list1 = List.of("A", "B", "C");
        List<Integer> list2 = List.of(1, 2, 3, 4, 5);
        
        // 空列表
        List<String> emptyList = List.of();
        
        // 单元素列表
        List<String> singletonList = List.of("OnlyOne");
        
        // 访问元素
        String element = list1.get(0);
        
        // 遍历
        for (String item : list1) {
            System.out.println(item);
        }
        
        // ⚠️ 不可修改
        // list1.add("D"); // 抛出 UnsupportedOperationException
        // list1.set(0, "NewA"); // 抛出 UnsupportedOperationException
        
        // ⚠️ 不允许 null 元素
        // List<String> listWithNull = List.of("A", null, "C"); // 抛出 NullPointerException
        
        // 转换为可修改列表
        List<String> modifiableList = new ArrayList<>(List.of("A", "B", "C"));
        modifiableList.add("D"); // 可以添加
    }
}

5. 性能对比

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class ListPerformanceComparison {
    public static void main(String[] args) {
        int size = 100000;
        
        // 测试 ArrayList
        List<Integer> arrayList = new ArrayList<>();
        long start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            arrayList.add(i);
        }
        long arrayListAdd = System.nanoTime() - start;
        
        // 测试 LinkedList
        List<Integer> linkedList = new LinkedList<>();
        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            linkedList.add(i);
        }
        long linkedListAdd = System.nanoTime() - start;
        
        // 测试 Vector
        Vector<Integer> vector = new Vector<>();
        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            vector.add(i);
        }
        long vectorAdd = System.nanoTime() - start;
        
        // 测试 CopyOnWriteArrayList
        CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<>();
        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            cowList.add(i);
        }
        long cowListAdd = System.nanoTime() - start;
        
        System.out.println("添加 " + size + " 个元素耗时:");
        System.out.println("ArrayList: " + arrayListAdd + " ns");
        System.out.println("LinkedList: " + linkedListAdd + " ns");
        System.out.println("Vector: " + vectorAdd + " ns");
        System.out.println("CopyOnWriteArrayList: " + cowListAdd + " ns");
        
        // 测试随机访问
        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            arrayList.get(i);
        }
        long arrayListGet = System.nanoTime() - start;
        
        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            linkedList.get(i);
        }
        long linkedListGet = System.nanoTime() - start;
        
        System.out.println("\n随机访问 " + size + " 次耗时:");
        System.out.println("ArrayList: " + arrayListGet + " ns");
        System.out.println("LinkedList: " + linkedListGet + " ns");
        
        // 测试头部插入
        start = System.nanoTime();
        arrayList.add(0, -1);
        long arrayListInsert = System.nanoTime() - start;
        
        start = System.nanoTime();
        linkedList.add(0, -1);
        long linkedListInsert = System.nanoTime() - start;
        
        System.out.println("\n头部插入耗时:");
        System.out.println("ArrayList: " + arrayListInsert + " ns");
        System.out.println("LinkedList: " + linkedListInsert + " ns");
    }
}

6. 选择指南

实现类 线程安全 随机访问 插入删除 适用场景
ArrayList O(1) O(n) 默认选择,频繁查询
LinkedList O(n) O(1) 频繁插入删除,实现栈/队列
Vector O(1) O(n) 旧代码,不推荐
Stack O(n) O(1) 旧代码,推荐 ArrayDeque
CopyOnWriteArrayList O(1) O(n) 读多写少的并发场景

7. 使用建议

默认选择

// 大多数情况下使用 ArrayList
List<String> list = new ArrayList<>();

需要频繁插入删除

// 使用 LinkedList
List<String> list = new LinkedList<>();

需要线程安全

// 读多写少:CopyOnWriteArrayList
List<String> list = new CopyOnWriteArrayList<>();

// 读写均衡:synchronizedList
List<String> list = Collections.synchronizedList(new ArrayList<>());

实现栈

// 推荐使用 ArrayDeque
Deque<String> stack = new ArrayDeque<>();
stack.push("A");
String top = stack.pop();

实现队列

// 推荐使用 ArrayDeque
Deque<String> queue = new ArrayDeque<>();
queue.offer("A");
String front = queue.poll();

创建不可变列表

// Java 9+
List<String> immutableList = List.of("A", "B", "C");

// Java 8
List<String> immutableList = Collections.unmodifiableList(Arrays.asList("A", "B", "C"));

8. 总结

Java 中的 List 接口有多种实现类,每种都有其特定的使用场景:

  1. ArrayList - 最常用,适合大多数场景
  2. LinkedList - 适合频繁插入删除
  3. Vector/Stack - 已过时,不推荐使用
  4. CopyOnWriteArrayList - 适合读多写少的并发场景
  5. 工具类方法 - 用于创建特殊类型的列表

在实际开发中,ArrayList 通常是默认选择,只有在特定需求下才考虑其他实现类。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐