首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java ArrayList 遍歷與增刪操作實戰:正確姿勢與併發陷阱

     編輯:Java 程式設計入門

核心類:ArrayList

  • 動態陣列實現 List 介面
  • 非執行緒安全,多執行緒環境需同步或用 CopyOnWriteArrayList
  • 隨機存取 O(1),尾部增刪 O(1),中間增刪 O(n)

基本操作範例

package com.example.list;

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

class Student {
    private String name;
    private int id;
    private String color;
    
    public Student(String name, int id, String color) {
        this.name = name;
        this.id = id;
        this.color = color;
    }
    // getter 省略
    public String getName() { return name; }
    public int getId() { return id; }
    public String getColor() { return color; }
}

public class ArrayListDemo {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        
        // 新增
        list.add(new Student("小紅", 13, "紅色"));
        list.add(new Student("小明", 12, "黃色"));
        list.add(new Student("小強", 123, "藍色"));
        
        // 指定位置插入
        list.add(1, new Student("小北", 2, "brave"));  // 索引 1 處插入
        
        // 刪除:按索引
        list.remove(0);  // 刪除第一個
        
        // 刪除:按物件(需正確實現 equals)
        Student toRemove = new Student("小李", 23, "白色");
        list.add(toRemove);
        list.remove(toRemove);  // 依賴 equals 比較
        
        // 遍歷方式對比
        System.out.println("=== for 迴圈 ===");
        for (int i = 0; i < list.size(); i++) {
            Student s = list.get(i);
            System.out.printf("%d: %s, %d, %s%n", i+1, s.getName(), s.getId(), s.getColor());
        }
        
        System.out.println("=== 增強 for ===");
        for (Student s : list) {
            System.out.println(s.getName());
        }
        
        System.out.println("=== Iterator(安全刪除) ===");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            if (s.getId() > 100) {
                it.remove();  // 唯一安全的遍歷中刪除方式
            }
        }
        
        System.out.println("=== Java 8 forEach ===");
        list.forEach(s -> System.out.println(s.getName()));
        
        System.out.println("=== Stream 過濾 ===");
        list.stream()
            .filter(s -> s.getId() < 50)
            .forEach(s -> System.out.println(s.getName() + " (ID<50)"));
    }
}

關鍵陷阱:遍歷中刪除

❌ 錯誤做法

// ConcurrentModificationException 必現
for (Student s : list) {
    if (s.getId() > 100) {
        list.remove(s);  // 直接修改結構,破壞迭代器預期
    }
}

// 索引迴圈刪除也會漏刪
for (int i = 0; i < list.size(); i++) {
    if (list.get(i).getId() > 100) {
        list.remove(i);  // 刪除後後續元素前移,i++ 導致跳過下一個
    }
}

✅ 正確做法

場景正確寫法
單執行緒,需邊遍歷邊刪使用 Iterator.remove()
單執行緒,先篩選後批量刪list.removeIf(s -> s.getId() > 100) (Java 8+)
單執行緒,創建新列表list = list.stream().filter(...).collect(toList())
多執行緒環境用 CopyOnWriteArrayList 或加鎖

效能特徵與選型

操作ArrayListLinkedListCopyOnWriteArrayList
隨機存取 get(i)O(1) ⭐O(n)O(1)
尾部新增 add(e)O(1) 擴容均攤O(1)O(n) 複製陣列
中間插入/刪除O(n) 移動元素O(1) 找到位置後O(n) 複製陣列
遍歷極快(緩存友好)較慢快
併發讀多寫少需外部同步需外部同步無鎖讀取 ⭐

最佳實踐總結

  1. 預設選 ArrayList:90% 場景下最優
  2. 指定初始容量:`new ArrayList<>(expectedSize)` 減少擴容複製
  3. 遍歷刪除用 removeIf/Iterator:避免 CME 異常
  4. 併發場景:讀多寫少 → CopyOnWriteArrayList;寫多 → Collections.synchronizedList 或並發隊列
  5. 不可變視圖:`List.of()` (Java 9+)、`Collections.unmodifiableList()`

總結

ArrayList 是 Java 開發最高頻的集合類。掌握其擴容機制、遍歷刪除正確姿勢、併發限制,能避開 80% 的生產故障。記住:有疑問時選 ArrayList,有併發時想清楚再選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved