Skip to content

14.2 ArrayList 集合使用

ArrayList 的概念

ArrayList 是 Java 中最常用的集合类之一,它实现了 List 接口,基于数组实现,提供了动态大小的数组功能。ArrayList 允许存储重复元素,并且可以通过索引快速访问元素。

ArrayList 的特点

  1. 基于数组:底层使用数组实现,支持随机访问
  2. 动态大小:容量会根据需要自动增长
  3. 允许重复元素:可以存储相同的元素
  4. 有序:保持元素的插入顺序
  5. 非线程安全:在多线程环境中需要额外的同步措施

ArrayList 的创建

1. 无参构造方法

创建一个初始容量为 10 的 ArrayList。

java
ArrayList<String> list = new ArrayList<>();

2. 指定初始容量

创建一个指定初始容量的 ArrayList。

java
ArrayList<String> list = new ArrayList<>(20); // 初始容量为 20

3. 从其他集合创建

通过其他集合创建 ArrayList。

java
List<String> otherList = Arrays.asList("Java", "Python", "C++");
ArrayList<String> list = new ArrayList<>(otherList);

ArrayList 的常用方法

1. 添加元素

add(E e)

功能:在列表末尾添加元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

add(int index, E element)

功能:在指定位置添加元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("C++");
list.add(1, "Python"); // 在索引 1 处添加 "Python"

addAll(Collection<? extends E> c)

功能:添加指定集合中的所有元素

示例

java
ArrayList<String> list1 = new ArrayList<>();
list1.add("Java");
list1.add("Python");

ArrayList<String> list2 = new ArrayList<>();
list2.add("C++");
list2.add("JavaScript");

list1.addAll(list2); // list1 现在包含 ["Java", "Python", "C++", "JavaScript"]

addAll(int index, Collection<? extends E> c)

功能:在指定位置添加指定集合中的所有元素

示例

java
ArrayList<String> list1 = new ArrayList<>();
list1.add("Java");
list1.add("C++");

ArrayList<String> list2 = new ArrayList<>();
list2.add("Python");
list2.add("JavaScript");

list1.addAll(1, list2); // list1 现在包含 ["Java", "Python", "JavaScript", "C++"]

2. 删除元素

remove(int index)

功能:删除指定索引处的元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

list.remove(1); // 删除索引 1 处的元素 "Python"

remove(Object o)

功能:删除指定的元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

list.remove("Python"); // 删除元素 "Python"

removeAll(Collection<?> c)

功能:删除指定集合中的所有元素

示例

java
ArrayList<String> list1 = new ArrayList<>();
list1.add("Java");
list1.add("Python");
list1.add("C++");
list1.add("JavaScript");

ArrayList<String> list2 = new ArrayList<>();
list2.add("Python");
list2.add("C++");

list1.removeAll(list2); // list1 现在包含 ["Java", "JavaScript"]

retainAll(Collection<?> c)

功能:保留指定集合中的元素,删除其他元素

示例

java
ArrayList<String> list1 = new ArrayList<>();
list1.add("Java");
list1.add("Python");
list1.add("C++");
list1.add("JavaScript");

ArrayList<String> list2 = new ArrayList<>();
list2.add("Python");
list2.add("C++");

list1.retainAll(list2); // list1 现在包含 ["Python", "C++"]

clear()

功能:清空集合中的所有元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

list.clear(); // 清空集合

3. 修改元素

set(int index, E element)

功能:修改指定索引处的元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

list.set(1, "JavaScript"); // 将索引 1 处的元素修改为 "JavaScript"

4. 查找元素

get(int index)

功能:获取指定索引处的元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

String element = list.get(0); // 获取索引 0 处的元素 "Java"

indexOf(Object o)

功能:获取指定元素第一次出现的索引

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("Java");

int index = list.indexOf("Java"); // 返回 0

lastIndexOf(Object o)

功能:获取指定元素最后一次出现的索引

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("Java");

int index = list.lastIndexOf("Java"); // 返回 2

contains(Object o)

功能:检查集合是否包含指定元素

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

boolean contains = list.contains("Python"); // 返回 true

5. 其他方法

size()

功能:获取集合的大小

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

int size = list.size(); // 返回 3

isEmpty()

功能:检查集合是否为空

示例

java
ArrayList<String> list = new ArrayList<>();
boolean isEmpty = list.isEmpty(); // 返回 true

list.add("Java");
isEmpty = list.isEmpty(); // 返回 false

toArray()

功能:将集合转换为数组

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

Object[] array = list.toArray();

toArray(T[] a)

功能:将集合转换为指定类型的数组

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

String[] array = list.toArray(new String[0]);

iterator()

功能:获取集合的迭代器

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

ArrayList 的遍历

1. for 循环

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

for (int i = 0; i < list.size(); i++) {
    String element = list.get(i);
    System.out.println(element);
}

2. 增强 for 循环

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

for (String element : list) {
    System.out.println(element);
}

3. 迭代器

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

4. forEach 方法(Java 8+)

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

list.forEach(element -> System.out.println(element));

ArrayList 的性能

时间复杂度

操作时间复杂度
随机访问(get/set)O(1)
头部插入/删除O(n)
尾部插入/删除O(1)
中间插入/删除O(n)
搜索O(n)

空间复杂度

  • 空间复杂度:O(n),其中 n 是元素数量

ArrayList 的扩容机制

ArrayList 的初始容量为 10,当元素数量超过当前容量时,会自动扩容。扩容的规则是:

  1. 当元素数量超过当前容量时,新容量为当前容量的 1.5 倍
  2. 如果新容量仍然不够,直接使用需要的容量

示例

java
ArrayList<String> list = new ArrayList<>(); // 初始容量 10

// 添加 10 个元素,容量仍为 10
for (int i = 0; i < 10; i++) {
    list.add("Element " + i);
}

// 添加第 11 个元素,容量会扩容到 15 (10 * 1.5)
list.add("Element 10");

示例:ArrayList 的使用

示例 1:基本操作

java
import java.util.ArrayList;

public class ArrayListBasicExample {
    public static void main(String[] args) {
        // 创建 ArrayList
        ArrayList<String> languages = new ArrayList<>();
        
        // 添加元素
        languages.add("Java");
        languages.add("Python");
        languages.add("C++");
        System.out.println("添加元素后: " + languages);
        
        // 在指定位置添加元素
        languages.add(1, "JavaScript");
        System.out.println("在指定位置添加元素后: " + languages);
        
        // 修改元素
        languages.set(2, "TypeScript");
        System.out.println("修改元素后: " + languages);
        
        // 删除元素
        languages.remove(3);
        System.out.println("删除元素后: " + languages);
        
        // 获取元素
        String first = languages.get(0);
        System.out.println("第一个元素: " + first);
        
        // 检查元素是否存在
        boolean contains = languages.contains("Java");
        System.out.println("是否包含 Java: " + contains);
        
        // 获取元素索引
        int index = languages.indexOf("TypeScript");
        System.out.println("TypeScript 的索引: " + index);
        
        // 获取集合大小
        int size = languages.size();
        System.out.println("集合大小: " + size);
        
        // 遍历集合
        System.out.println("遍历集合:");
        for (String language : languages) {
            System.out.println("- " + language);
        }
        
        // 清空集合
        languages.clear();
        System.out.println("清空后: " + languages);
        System.out.println("清空后大小: " + languages.size());
    }
}

示例 2:存储自定义对象

java
import java.util.ArrayList;

class Student {
    private String name;
    private int age;
    
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
}

public class ArrayListObjectExample {
    public static void main(String[] args) {
        // 创建 ArrayList 存储 Student 对象
        ArrayList<Student> students = new ArrayList<>();
        
        // 添加学生对象
        students.add(new Student("Alice", 18));
        students.add(new Student("Bob", 19));
        students.add(new Student("Charlie", 20));
        
        // 打印学生列表
        System.out.println("学生列表: " + students);
        
        // 获取学生
        Student firstStudent = students.get(0);
        System.out.println("第一个学生: " + firstStudent);
        
        // 修改学生
        students.set(1, new Student("David", 21));
        System.out.println("修改后学生列表: " + students);
        
        // 删除学生
        students.remove(2);
        System.out.println("删除后学生列表: " + students);
        
        // 遍历学生列表
        System.out.println("遍历学生列表:");
        for (Student student : students) {
            System.out.println("- " + student.getName() + " (" + student.getAge() + "岁)");
        }
    }
}

示例 3:ArrayList 与数组的转换

java
import java.util.ArrayList;
import java.util.Arrays;

public class ArrayListArrayConversionExample {
    public static void main(String[] args) {
        // 从数组创建 ArrayList
        String[] array = {"Java", "Python", "C++"};
        ArrayList<String> list = new ArrayList<>(Arrays.asList(array));
        System.out.println("从数组创建的 ArrayList: " + list);
        
        // 从 ArrayList 创建数组
        String[] newArray = list.toArray(new String[0]);
        System.out.println("从 ArrayList 创建的数组: " + Arrays.toString(newArray));
        
        // 从 ArrayList 创建指定大小的数组
        String[] newArray2 = list.toArray(new String[list.size()]);
        System.out.println("从 ArrayList 创建的指定大小数组: " + Arrays.toString(newArray2));
    }
}

示例 4:ArrayList 的排序

java
import java.util.ArrayList;
import java.util.Collections;

public class ArrayListSortExample {
    public static void main(String[] args) {
        // 创建 ArrayList
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(9);
        
        System.out.println("排序前: " + numbers);
        
        // 升序排序
        Collections.sort(numbers);
        System.out.println("升序排序后: " + numbers);
        
        // 降序排序
        Collections.sort(numbers, Collections.reverseOrder());
        System.out.println("降序排序后: " + numbers);
        
        // 字符串排序
        ArrayList<String> languages = new ArrayList<>();
        languages.add("Java");
        languages.add("Python");
        languages.add("C++");
        languages.add("JavaScript");
        
        System.out.println("字符串排序前: " + languages);
        
        // 按字典序排序
        Collections.sort(languages);
        System.out.println("字符串排序后: " + languages);
    }
}

常见问题

1. 索引越界

症状IndexOutOfBoundsException

解决方案:在访问元素前,确保索引在有效范围内

示例

java
ArrayList<String> list = new ArrayList<>();
list.add("Java");

// 错误:索引越界
// String element = list.get(1);

// 正确:检查索引范围
if (index >= 0 && index < list.size()) {
    String element = list.get(index);
}

2. 空指针异常

症状NullPointerException

解决方案:在使用集合前,检查集合是否为 null

示例

java
ArrayList<String> list = null;

// 错误:空指针异常
// list.add("Java");

// 正确:检查集合是否为 null
if (list != null) {
    list.add("Java");
} else {
    list = new ArrayList<>();
    list.add("Java");
}

3. 性能问题

症状:ArrayList 操作速度慢

解决方案

  • 对于频繁的插入和删除操作,考虑使用 LinkedList
  • 合理设置初始容量,减少扩容操作
  • 对于大数据量,考虑使用更高效的数据结构

示例

java
// 合理设置初始容量
ArrayList<String> list = new ArrayList<>(1000); // 初始容量为 1000

// 对于频繁插入删除,使用 LinkedList
List<String> list = new LinkedList<>();

4. 线程安全问题

症状:在多线程环境中,ArrayList 操作导致数据不一致

解决方案:使用线程安全的集合或同步机制

示例

java
// 使用线程安全的集合
List<String> list = Collections.synchronizedList(new ArrayList<>());

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

最佳实践

  1. 合理设置初始容量:根据预期的元素数量,合理设置初始容量,减少扩容操作

  2. 选择合适的集合:对于频繁的插入和删除操作,考虑使用 LinkedList;对于频繁的随机访问,使用 ArrayList

  3. 使用泛型:使用泛型确保类型安全,避免运行时异常

  4. 注意线程安全:在多线程环境中,使用线程安全的集合或同步机制

  5. 避免不必要的装箱拆箱:对于基本数据类型,考虑使用原始类型的集合(如 IntArrayList)

  6. 使用合适的遍历方式:对于 ArrayList,使用索引遍历或增强 for 循环

  7. 及时清理:对于不再使用的 ArrayList,及时清空或设置为 null,帮助垃圾回收

总结

ArrayList 是 Java 中最常用的集合类之一,它基于数组实现,提供了动态大小的数组功能。ArrayList 的主要特点:

  1. 基于数组:支持随机访问,时间复杂度为 O(1)
  2. 动态大小:容量会根据需要自动增长
  3. 允许重复元素:可以存储相同的元素
  4. 有序:保持元素的插入顺序
  5. 非线程安全:在多线程环境中需要额外的同步措施

ArrayList 适用于需要频繁随机访问元素的场景,而对于频繁插入和删除操作的场景,建议使用 LinkedList

通过合理使用 ArrayList,可以提高代码的效率和可维护性。

© 2026 编程马·菜鸟教程 版权所有