一、 ArrayList 的核心定位
ArrayList 是 Java 集合框架中List接口的可变数组实现,对比我们初学的普通数组:
普通数组:长度固定,一旦创建就不能修改,增删元素需要手动新建数组复制
ArrayList:长度动态可变,底层自动维护数组扩容 / 缩容,提供了丰富的操作方法(增删改查)
注意:ArrayList 只能存储引用类型(如 String、Integer),不能直接存基本类型(int、double),需要用对应的包装类
二、ArrayList 基础操作

举个例子:

import java.util.ArrayList;
import java.util.List;

public class ArrayListBasic {
    public static void main(String[] args) {
        // 1. 创建ArrayList:指定泛型(String),限定只能存字符串类型
        List<String> fruitList = new ArrayList<>();

        // 2. 新增元素:add()方法(尾部添加)
        fruitList.add("苹果");
        fruitList.add("香蕉");
        fruitList.add("橙子");
        System.out.println("添加元素后:" + fruitList); // 输出:[苹果, 香蕉, 橙子]

        // 3. 指定位置新增元素:add(索引, 元素)
        fruitList.add(1, "草莓"); // 在索引1的位置插入草莓
        System.out.println("指定位置添加后:" + fruitList); // 输出:[苹果, 草莓, 香蕉, 橙子]

        // 4. 获取元素:get(索引)
        String firstFruit = fruitList.get(0);
        System.out.println("索引0的元素:" + firstFruit); // 输出:苹果

        // 5. 修改元素:set(索引, 新值)
        fruitList.set(2, "蓝莓"); // 把索引2的香蕉改成蓝莓
        System.out.println("修改后:" + fruitList); // 输出:[苹果, 草莓, 蓝莓, 橙子]

        // 6. 删除元素:两种方式
        fruitList.remove(3); // 按索引删除(删除橙子)
        // fruitList.remove("草莓"); // 按元素值删除(删除草莓)
        System.out.println("删除后:" + fruitList); // 输出:[苹果, 草莓, 蓝莓]

        // 7. 遍历ArrayList:三种常用方式
        System.out.println("\n=== 遍历方式1:普通for循环(可操作索引)==");
        for (int i = 0; i < fruitList.size(); i++) {
            System.out.println("索引" + i + ":" + fruitList.get(i));
        }

        System.out.println("\n=== 遍历方式2:增强for循环(简洁)==");
        for (String fruit : fruitList) {
            System.out.println(fruit);
        }

        System.out.println("\n=== 遍历方式3:forEach Lambda==");
        fruitList.forEach(fruit -> System.out.println(fruit));

        // 8. 其他常用方法
        System.out.println("\n集合大小:" + fruitList.size()); // 输出:3
        System.out.println("是否包含苹果:" + fruitList.contains("苹果")); // 输出:true
        System.out.println("苹果的索引:" + fruitList.indexOf("苹果")); // 输出:0
        fruitList.clear(); // 清空集合
        System.out.println("清空后:" + fruitList); // 输出:[]
        System.out.println("是否为空:" + fruitList.isEmpty()); // 输出:true
    }
}

三、 ArrayList 的核心特性
1. 动态扩容机制
ArrayList 底层是一个Object[]数组,默认初始容量是 10。当添加元素导致数组满了时,会自动扩容:
扩容规则:新容量 = 原容量 * 1.5
本质:新建一个更大的数组,把原数组的元素复制过去
用代码直观感受扩容(重点理解 “动态”):

import java.util.ArrayList;

public class ArrayListExpand {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        // 连续添加11个元素(超过默认初始容量10)
        for (int i = 1; i <= 11; i++) {
            list.add(i);
            System.out.println("添加第" + i + "个元素后,集合大小:" + list.size());
        }
        // 输出会看到集合大小从1到11,说明自动扩容了,不用手动处理
    }
}

2. 泛型的作用(避免类型错误)
如果创建时不指定泛型,ArrayList 会变成 “万能容器”,容易出现类型转换异常,我们一定要养成指定泛型的习惯:

import java.util.ArrayList;

public class ArrayListGeneric {
    public static void main(String[] args) {
        // 错误示范:不指定泛型,能存任意类型
        ArrayList badList = new ArrayList();
        badList.add("字符串");
        badList.add(123); // 存整数
        // 取元素时需要强制类型转换,容易报错
        String s = (String) badList.get(1); // 运行时报错:Integer不能转String

        // 正确示范:指定泛型<Integer>,只能存整数
        ArrayList<Integer> goodList = new ArrayList<>();
        goodList.add(123);
        // goodList.add("字符串"); // 编译时就报错,提前规避问题
        int num = goodList.get(0); // 无需强制转换
    }
}

3. ArrayList vs 普通数组(互转示例)

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

public class ArrayListVsArray {
    public static void main(String[] args) {
        // 1. ArrayList转普通数组
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        // toArray()方法:注意指定数组类型
        String[] arr = list.toArray(new String[0]);
        System.out.println("ArrayList转数组:" + Arrays.toString(arr)); // 输出:[A, B]

        // 2. 普通数组转ArrayList
        String[] arr2 = {"X", "Y", "Z"};
        ArrayList<String> list2 = new ArrayList<>(Arrays.asList(arr2));
        System.out.println("数组转ArrayList:" + list2); // 输出:[X, Y, Z]
    }
}

四、常见易错点
1. 遍历删除元素的坑
增强 for 循环中直接删除元素会抛出ConcurrentModificationException,正确方式用迭代器或普通 for 循环(倒序):

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListRemoveError {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        // 错误方式:增强for循环删除
        /*
        for (String s : list) {
            if (s.equals("b")) {
                list.remove(s); // 抛出ConcurrentModificationException
            }
        }
        */

        // 正确方式1:迭代器删除
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if (s.equals("b")) {
                it.remove(); // 用迭代器的remove方法
            }
        }
        System.out.println("迭代器删除后:" + list); // 输出:[a, c]

        // 正确方式2:普通for循环(倒序)
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("1");
        list2.add("2");
        list2.add("3");
        for (int i = list2.size() - 1; i >= 0; i--) {
            if (list2.get(i).equals("2")) {
                list2.remove(i);
            }
        }
        System.out.println("倒序删除后:" + list2); // 输出:[1, 3]
    }
}

2. 索引越界异常
常犯:获取 / 删除元素时索引超出集合大小,比如集合只有 3 个元素(索引 0-2),却去 get (3):

ArrayList<String> list = new ArrayList<>();
list.add("a");
// list.get(1); // 报错:索引1超出范围(当前大小1)
// 规避:操作索引前先判断大小
if (list.size() > 1) {
    System.out.println(list.get(1));
} else {
    System.out.println("索引不存在");
}

总结
核心特性:ArrayList 是动态可变数组,底层自动扩容,相比普通数组更灵活,但增删中间元素效率较低(需要移动元素)。
基础使用:掌握add/get/set/remove/size/contains等核心方法,遍历优先用增强 for 或 Lambda。
避坑要点:指定泛型避免类型错误,遍历删除用迭代器 / 倒序 for 循环,操作索引前先检查集合大小。

Logo

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

更多推荐