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

Java List 去重完全指南:從 HashSet 到 Stream API 與自定義對象策略

     編輯:Java 相關知識

核心原理:Set 不重複特性

HashSet 底層基於 HashMap,通過 hashCode() + equals() 判斷元素唯一性。利用「List → Set → List」轉換即可去重,但**順序不保證**。

基礎去重代碼

1. Java 7- (無鑽石操作符)

List listWithDup = Arrays.asList("1", "2", "3", "1");
List listWithoutDup = new ArrayList(new HashSet(listWithDup));
// 結果: [1, 2, 3] 順序不定

2. Java 7+ (鑽石操作符 <>)

List listWithoutDup = new ArrayList<>(new HashSet<>(listWithDup));

3. Java 8+ Stream API (推薦,可保持順序)

// 保持首次出現順序
List distinct = listWithDup.stream().distinct().collect(Collectors.toList());

// 或配合 LinkedHashSet 保序
List distinct = listWithDup.stream()
    .collect(Collectors.toCollection(LinkedHashSet::new))
    .stream().collect(Collectors.toList());

自定義對象去重:關鍵在 hashCode/equals

@Data @AllArgsConstructor
class User {
    private Long id;
    private String name;
    // 必須重寫 hashCode & equals,否則去重失效!
}
  • IDE 自動生成或 Lombok @EqualsAndHashCode。
  • 僅按 id 去重 → @EqualsAndHashCode(of = "id")。

進階場景與性能對比

場景推薦方案時間複雜度空間複雜度順序
基本類型/String、無序要求HashSet 構造器O(n)O(n)無序
基本類型/String、保持順序LinkedHashSet / Stream.distinct()O(n)O(n)有序
自定義對象、海量數據 (百萬+)並行流 parallelStream().distinct()O(n/p)O(n)無序
按特定字段去重 (如 id)Stream + TreeSet(comparing) / Map(key=字段)O(n log n)O(n)可控
原地去重 (不創建新集合)Iterator + Set 記錄見過元素O(n)O(k)有序

原地去重範例 (保持順序、不創建新 List)

public static  void distinctInPlace(List list) {
    Set seen = new HashSet<>();
    Iterator it = list.iterator();
    while (it.hasNext()) {
        if (!seen.add(it.next())) it.remove(); // add 返回 false 表示重複
    }
}

避坑指南

  1. 未重寫 hashCode/equals:自定義對象去重失效,視為不同對象。
  2. 並發修改異常:遍歷時直接 list.remove() 必須用 Iterator.remove()。
  3. null 元素:HashSet 允許單個 null,TreeSet 不允許。
  4. 大數據量:預估去重後大小,預分配 new ArrayList<>(expectedSize) 避免擴容。

總結

「List → Set → List」是最簡潔去重模式;需保序用 LinkedHashSet 或 Stream.distinct();自定義對象**務必正確重寫 hashCode/equals**。根據數據量、順序要求、字段粒度選擇最優方案,兼顧可讀性與性能。

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