Java ArrayList(集合) 常用 API

一、创建和初始化

1. 创建 ArrayList

java 复制代码
// 1. 默认初始容量10
ArrayList<String> list1 = new ArrayList<>();

// 2. 指定初始容量
ArrayList<String> list2 = new ArrayList<>(50);

// 3. 从其他集合创建
List<String> existingList = Arrays.asList("A", "B", "C");
ArrayList<String> list3 = new ArrayList<>(existingList);

// 4. Java 10+ 使用 var
var list4 = new ArrayList<Integer>();

// 5. 使用 Collections 工具类
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());

2. 快速初始化

java 复制代码
// Java 9+ 工厂方法(返回的是不可变List)
List<String> fixedList = List.of("A", "B", "C");

// 如果需要可变的ArrayList
ArrayList<String> mutableList = new ArrayList<>(List.of("A", "B", "C"));

// 传统方式
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "A", "B", "C");

二、添加元素

1. 基本添加操作

java 复制代码
ArrayList<String> list = new ArrayList<>();

// 1. 添加到末尾
list.add("Apple");                      // ["Apple"]
list.add("Banana");                     // ["Apple", "Banana"]
boolean added = list.add("Cherry");     // true, ["Apple", "Banana", "Cherry"]

// 2. 添加到指定位置
list.add(1, "Orange");                  // ["Apple", "Orange", "Banana", "Cherry"]

// 3. 添加多个元素
list.addAll(List.of("Grape", "Mango")); // ["Apple", "Orange", "Banana", "Cherry", "Grape", "Mango"]
list.addAll(2, List.of("Pear", "Peach")); // 从指定位置添加

三、访问和修改元素

1. 获取元素

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));

// 1. 获取指定位置
String first = list.get(0);             // "A"

// 2. 获取第一个和最后一个
String first2 = list.getFirst();        // Java 21+ "A"
String last = list.getLast();           // Java 21+ "D"

// 3. 获取子列表(视图,共享底层数组)
List<String> subList = list.subList(1, 3); // ["B", "C"](不包括索引3)

2. 修改元素

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));

// 修改指定位置元素
String old = list.set(1, "BB");         // 返回旧值:"B",列表变为["A", "BB", "C"]

四、删除元素

1. 按索引删除

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));

// 删除指定位置
String removed = list.remove(1);        // 返回被删除的"B",列表变为["A", "C", "D"]

2. 按元素删除

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C", "B"));

// 删除第一次出现的元素
boolean removed = list.remove("B");     // true,列表变为["A", "C", "B"]

// 删除所有匹配元素(Java 8+)
list.removeIf(s -> s.startsWith("A"));  // 删除所有以"A"开头的元素

// 删除多个元素
list.removeAll(List.of("B", "C"));      // 删除所有"B"和"C"
list.retainAll(List.of("A", "D"));      // 只保留"A"和"D",删除其他

3. 清空列表

java 复制代码
list.clear();                           // 清空所有元素

五、查找和判断

1. 查找元素

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C", "B", "A"));

// 1. 判断包含
boolean hasA = list.contains("A");      // true
boolean hasAll = list.containsAll(List.of("A", "B")); // true

// 2. 查找索引
int firstIndex = list.indexOf("B");     // 1(第一次出现)
int lastIndex = list.lastIndexOf("B");  // 3(最后一次出现)
int notFound = list.indexOf("X");       // -1(未找到)

2. 列表信息

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));

int size = list.size();                 // 3
boolean empty = list.isEmpty();         // false

六、遍历和迭代

1. 不同遍历方式

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));

// 1. for循环
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 2. 增强for循环
for (String item : list) {
    System.out.println(item);
}

// 3. 迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
    if ("B".equals(item)) {
        iterator.remove();  // 安全删除
    }
}

// 4. ListIterator(双向遍历)
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
    System.out.println(listIterator.next());
}
while (listIterator.hasPrevious()) {
    System.out.println(listIterator.previous());
}

// 5. Java 8+ forEach
list.forEach(item -> System.out.println(item));
list.forEach(System.out::println);

2. 并行遍历

java 复制代码
// 并行流遍历(Java 8+)
list.parallelStream().forEach(item -> {
    System.out.println(Thread.currentThread().getName() + ": " + item);
});

七、转换和操作

1. 转换为数组

java 复制代码
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));

// 1. 转换为Object数组
Object[] array1 = list.toArray();       // Object[]

// 2. 转换为指定类型数组
String[] array2 = list.toArray(new String[0]); // String[]
String[] array3 = list.toArray(String[]::new); // Java 11+ 方法引用

2. 排序和反转

java 复制代码
ArrayList<Integer> numbers = new ArrayList<>(List.of(3, 1, 4, 1, 5));

// 1. 自然排序
Collections.sort(numbers);              // [1, 1, 3, 4, 5]

// 2. 自定义排序
numbers.sort(Comparator.reverseOrder()); // [5, 4, 3, 1, 1]

// 3. 反转
Collections.reverse(numbers);           // [1, 1, 3, 4, 5] -> [5, 4, 3, 1, 1]

// 4. 打乱顺序
Collections.shuffle(numbers);           // 随机打乱

八、Stream API 操作(Java 8+)

java 复制代码
ArrayList<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4, 5));

// 1. 过滤
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());      // [2, 4]

// 2. 映射
List<String> strings = numbers.stream()
    .map(n -> "Number: " + n)
    .collect(Collectors.toList());

// 3. 统计
long count = numbers.stream().count();  // 5
int sum = numbers.stream().mapToInt(Integer::intValue).sum(); // 15
Optional<Integer> max = numbers.stream().max(Integer::compare);

// 4. 分组
Map<Boolean, List<Integer>> partitioned = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n > 3));
// {false=[1,2,3], true=[4,5]}

九、容量和性能

1. 容量管理

java 复制代码
ArrayList<String> list = new ArrayList<>();

// 确保最小容量
list.ensureCapacity(100);               // 提前分配空间,避免多次扩容

// 缩减容量到实际大小
list.trimToSize();                      // 释放多余空间

2. 性能提示

java 复制代码
// 1. 预分配容量(避免频繁扩容)
ArrayList<String> list = new ArrayList<>(1000);

// 2. 批量操作 vs 单个操作
// ❌ 低效(多次扩容)
for (int i = 0; i < 1000; i++) {
    list.add("item" + i);
}

// ✅ 高效
list.addAll(Collections.nCopies(1000, "item"));

// 3. 使用合适的遍历方式
// 随机访问用 for-i 循环
for (int i = 0; i < list.size(); i++) {
    list.get(i);  // O(1) 时间复杂度
}

十、线程安全处理

1. 同步包装

java 复制代码
// 创建线程安全的ArrayList
List<String> syncList = Collections.synchronizedList(new ArrayList<>());

// 使用时需要手动同步
synchronized(syncList) {
    syncList.add("item");
    // 遍历也需要同步
    for (String item : syncList) {
        System.out.println(item);
    }
}

2. CopyOnWriteArrayList(读多写少场景)

java 复制代码
import java.util.concurrent.CopyOnWriteArrayList;

CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();
safeList.add("item");  // 线程安全,每次写操作复制底层数组

十一、实际应用示例

java 复制代码
public class ArrayListExample {
    public static void main(String[] args) {
        // 1. 学生成绩管理
        ArrayList<Integer> scores = new ArrayList<>();
        scores.add(85);
        scores.add(92);
        scores.add(78);
        
        // 计算平均分
        double average = scores.stream()
            .mapToInt(Integer::intValue)
            .average()
            .orElse(0.0);
        
        // 2. 购物车实现
        class ShoppingCart {
            private ArrayList<String> items = new ArrayList<>();
            
            public void addItem(String item) {
                items.add(item);
            }
            
            public void removeItem(String item) {
                items.remove(item);
            }
            
            public List<String> getItems() {
                return new ArrayList<>(items); // 返回副本
            }
        }
        
        // 3. 数据过滤和转换
        ArrayList<String> rawData = new ArrayList<>(
            List.of("apple", "banana", "cherry", "date", "elderberry")
        );
        
        // 过滤长度大于5的字符串并转换为大写
        List<String> processed = rawData.stream()
            .filter(s -> s.length() > 5)
            .map(String::toUpperCase)
            .collect(Collectors.toList());
        // ["ELDERBERRY"]
    }
}

十二、常见问题及解决

1. ConcurrentModificationException

java 复制代码
// ❌ 错误:遍历时修改列表
ArrayList<String> list = new ArrayList<>(List.of("A", "B", "C"));
for (String item : list) {
    if ("B".equals(item)) {
        list.remove(item);  // 抛出异常!
    }
}

// ✅ 正确1:使用迭代器删除
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if ("B".equals(it.next())) {
        it.remove();  // 安全删除
    }
}

// ✅ 正确2:Java 8+ removeIf
list.removeIf(item -> "B".equals(item));

2. 空值处理

java 复制代码
ArrayList<String> list = new ArrayList<>();
list.add(null);  // ArrayList允许null值

// 检查时注意
if (list.contains(null)) {
    System.out.println("列表包含null");
}

总结要点

  1. 动态数组:自动扩容,初始容量10,每次扩容1.5倍
  2. 随机访问get(index) 是 O(1) 时间复杂度
  3. 非线程安全:多线程环境需要外部同步
  4. 允许null:可以存储null元素
  5. 快速失败:迭代器是快速失败的
  6. 性能优化:预分配容量,批量操作
  7. 现代用法:结合Stream API进行函数式操作
相关推荐
马卡巴卡1 小时前
Kafka:消费者重试与死信队列的对应模式分析
后端
落枫591 小时前
String.join(",", List) VS List.stream().collect(Collectors.joining(",")) 哪种效率好
后端
咕白m6251 小时前
Python 实现 Word 到 Markdown 的转换
后端·python
哈哈哈笑什么1 小时前
企业级CompletableFuture并行化完整方案,接口从10s到100ms
java·后端·spring cloud
脑极体1 小时前
蓝河入海:Rust先行者vivo的开源之志
开发语言·后端·rust·开源
源代码•宸1 小时前
GoLang并发简单例子(goroutine + channel + WaitGroup)
开发语言·经验分享·后端·学习·golang
稚辉君.MCA_P8_Java1 小时前
Gemini永久会员 Go 返回最长有效子串长度
数据结构·后端·算法·golang
李少兄2 小时前
解决 Spring Boot 中 YAML 配置文件的 `ArrayIndexOutOfBoundsException: -1` 异常
java·spring boot·后端