教程中心 / Java教程 / List集合

List集合

20分钟 集合框架

引言:什么是集合?

集合(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 在线代码编辑器
📝 运行结果