List 去重是高頻操作,本文總結三種主流寫法、性能特點與適用場景。
| JDK 版本 | 代碼 | 特點 |
|---|---|---|
| 所有版本 | List<T> uniq = new ArrayList<>(new HashSet<>(list)); | 最簡潔,利用 HashSet 去重特性,不保留原順序。 |
| Java 7+ | List<T> uniq = new ArrayList<>(new HashSet<>(list)); (鑽石語法) | 同上,類型推斷更簡潔。 |
| Java 8+ | List<T> uniq = list.stream().distinct().collect(Collectors.toList()); | 保留原順序,函數式風格,可並行 .parallelStream()。 |
| Java 8+ | List<T> uniq = new ArrayList<>(new LinkedHashSet<>(list)); | 保留原順序,性能優於 Stream,推薦生產環境。 |
import java.util.*;
public class ListDeduplicateDemo {
public static void main(String[] args) {
List listWithDup = Arrays.asList("1", "2", "3", "1", "2", "4");
// 1. HashSet - 無序
List unordered = new ArrayList<>(new HashSet<>(listWithDup));
System.out.println("HashSet: " + unordered); // [1, 2, 3, 4] 順序不定
// 2. LinkedHashSet - 有序
List ordered = new ArrayList<>(new LinkedHashSet<>(listWithDup));
System.out.println("LinkedHashSet: " + ordered); // [1, 2, 3, 4] 保留首次出現順序
// 3. Stream distinct - 有序
List streamed = listWithDup.stream().distinct().collect(Collectors.toList());
System.out.println("Stream: " + streamed); // [1, 2, 3, 4]
}
}
LinkedHashSet 兼顧有序與簡潔。LinkedHashSet 單次遍歷 O(N),常數因子最小;Stream 多一次 Lambda 開銷。CopyOnWriteArrayList + LinkedHashSet,或並發流 list.parallelStream().distinct()(注意順序不保證)。equals() 與 hashCode(),否則去重失效。new HashSet(list) 後再 list.clear(); list.addAll(set) 會改變原列表引用,影響其他持有者。List<int>)不可用,需裝箱 List<Integer>。HashSet 允許單個 null,distinct() 同樣保留一個 null。