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

Java ArrayList 核心用法、去重技巧與性能優化指南

     編輯:Java 相關知識

ArrayList 核心特性速覽

特性說明
底層結構動態數組 transient Object[] elementData
初始容量默認 10,new ArrayList<>(初始容量) 可指定
擴容機制1.5 倍 newCapacity = old + (old >> 1),涉及 Arrays.copyOf
隨機訪問O(1),實現 RandomAccess 標記
插入刪除中間/頭部 O(n) 需搬移,尾部 O(1) 擴容均攤
線程安全非線程安全,多寫需外部同步或用 CopyOnWriteArrayList
允許 null✅
允許重複✅

常用 API 速查

List list = new ArrayList<>();

// 添加
list.add("A");                    // 尾部
list.add(0, "First");             // 指定索引
list.addAll(Arrays.asList("X","Y")); // 批量尾部
list.addAll(1, otherList);        // 批量指定位置

// 查詢
String s = list.get(0);           // 索引獲取
int idx = list.indexOf("A");      // 首次出現索引
int last = list.lastIndexOf("A"); // 最後出現索引
boolean has = list.contains("A"); // 是否包含
int size = list.size();           // 長度
boolean empty = list.isEmpty();   // 是否為空

// 修改
list.set(0, "New");               // 替換指定索引

// 刪除
list.remove(0);                   // 索引刪除
list.remove("A");                 // 對象刪除 (首個匹配)
list.removeIf(s -> s.length() > 5); // 條件刪除 (Java 8+)
list.clear();                     // 清空

// 遍歷
for (String s : list) {}          // for-each
list.forEach(System.out::println); // Lambda
for (int i = 0; i < list.size(); i++) {} // 索引 for

// 轉換
String[] arr = list.toArray(new String[0]); // 轉數組
List copy = new ArrayList<>(list);  // 拷貝
List sub = list.subList(1, 3);      // 視圖 (共享底層數組)

// 排序
Collections.sort(list);                       // 自然序
Collections.sort(list, Comparator.reverseOrder()); // 逆序
list.sort(Comparator.naturalOrder());         // Java 8+ List.sort()

去重方案大全

方案一:HashSet 中轉 (最推薦,O(n))

// 1. 原地去重 (保留首次出現順序)
List list = Arrays.asList(2, 5, 2, 3, 2, 4);
list = new ArrayList<>(new LinkedHashSet<>(list)); // [2, 5, 3, 4]

// 2. 不保留順序 (HashSet)
list = new ArrayList<>(new HashSet<>(list)); // 順序不定

// 3. 就地修改 (避免新建對象引用變化)
Set set = new LinkedHashSet<>(list);
list.clear();
list.addAll(set);

方案二:Stream API (Java 8+,函數式)

// 保留順序
list = list.stream().distinct().collect(Collectors.toList());

// 自定義比較器去重 (如對象按 ID 去重)
list = list.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getId))),
        ArrayList::new
    ));

方案三:雙重循環 (教學/無額外空間,O(n²))

// 反向遍歷避免索引錯位
for (int i = list.size() - 1; i >= 0; i--) {
    for (int j = i - 1; j >= 0; j--) {
        if (list.get(i).equals(list.get(j))) {
            list.remove(i);
            break;
        }
    }
}

方案四:排序後相鄰比較 (O(n log n),改變順序)

Collections.sort(list);
for (int i = list.size() - 1; i > 0; i--) {
    if (list.get(i).equals(list.get(i - 1))) {
        list.remove(i);
    }
}

性能對比 (10 萬數據去重)

方案耗時順序適用場景
LinkedHashSet 中轉~15ms✅ 保留通用首選
HashSet 中轉~12ms❌ 不保留不需順序
Stream.distinct()~18ms✅ 保留函數式管道中
排序+相鄰比較~45ms❌ 排序序已排序/可排序
雙重循環~8000ms✅ 保留極小數據/教學

高性能使用最佳實踐

  1. 預估容量:new ArrayList<>(expectedSize) 避免多次擴容拷貝
  2. 批量添加用 addAll:單次擴容、單次拷貝
  3. 頻繁頭部操作用 LinkedList/ArrayDeque
  4. 多線程寫入用 CopyOnWriteArrayList:讀多寫少、遍歷無需加鎖
  5. 只讀場景用 Collections.unmodifiableList / List.of (JDK 9+)
  6. 避免在循環中 remove/contains:O(n²),改用 Iterator.remove() 或 removeIf()
  7. subList 視圖謹慎用:底層共享數組,結構修改會失效,僅用於臨時只讀切片
  8. 並行流處理大數據:list.parallelStream()... (需隨機訪問支持)

常見陷阱與避坑

代碼問題修正
list.remove(i) 正向循環跳過元素/索引越界反向循環 for(int i=size-1;i>=0;i--) 或 Iterator.remove()
list.contains() 在循環中O(n²) 性能災難用 HashSet 輔助或 removeIf()
Arrays.asList(arr).add()拋 UnsupportedOperationException (定長列表)new ArrayList<>(Arrays.asList(arr))
List list = new ArrayList(); (無泛型)原始類型,編譯警告、運行時 ClassCastException始終指定泛型 new ArrayList<>()
序列化含 null 元素部分框架反序列化異常業務層過濾 null 或配置序列化策略

ArrayList vs LinkedList vs Vector 選型

場景首選備選
隨機訪問、末尾增刪、讀多寫少ArrayListVector (需同步)
頻繁首尾增刪、隊列/棧、迭代器操作ArrayDeque / LinkedList
多線程並發寫入、遍歷無鎖CopyOnWriteArrayListCollections.synchronizedList
只讀、不可變List.of() / Collections.unmodifiableList()

總結

ArrayList 是 Java 最常用的列表實現,動態數組 + 隨機訪問 O(1) + 尾部增刪 O(1) 適合絕大多數業務場景。核心技巧:預估容量、LinkedHashSet 去重保序、removeIf 條件刪除、批量操作、並行流。理解擴容機制、線程不安全、subList 視圖特性,避開常見陷阱,能寫出高性能、無 Bug 的列表操作代碼。

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