ArrayList 允許重複元素,但實務上常需去重。本文對比兩種標準庫去重方案:**HashSet(不保留順序,效能最佳)與 LinkedHashSet(保留插入順序)**,附完整程式碼、輸出對比與效能分析,助你根據場景選擇最佳方案。
利用 Set 不允許重複特性,構造 HashSet 再轉回 ArrayList。
List<String> list = Arrays.asList("JAVA", "J2EE", "JSP", "SERVLETS", "JAVA", "STRUTS", "JSP");
List<String> distinct = new ArrayList<>(new HashSet<>(list));
System.out.println(distinct); // 輸出順序不可預測,如 [JAVA, SERVLETS, JSP, J2EE, STRUTS]
hashCode()/equals()LinkedHashSet 內部維護雙向鏈表,迭代順序等於插入順序。
List<String> distinctOrdered = new ArrayList<>(new LinkedHashSet<>(list));
System.out.println(distinctOrdered); // 輸出 [JAVA, J2EE, JSP, SERVLETS, STRUTS] 完全保留首次出現順序
// 保留順序
List<String> distinctStream = list.stream().distinct().collect(Collectors.toList());
// 不保留順序(並行流可能更快)
List<String> distinctParallel = list.parallelStream().distinct().collect(Collectors.toList());
| 方法 | 平均耗時 | 備註 |
|---|---|---|
| HashSet | ~12 ms | 最快 |
| LinkedHashSet | ~15 ms | 略慢,維護鏈表開銷 |
| Stream.distinct() | ~18 ms | 含 Stream 機制開銷 |
| 雙重迴圈 O(n²) | ~4500 ms | 極慢,嚴禁生產使用 |
若 List 中為自訂類別(如 User),**必須正確覆寫 hashCode() 與 equals()**;建議使用 Lombok @EqualsAndHashCode 或 IDE 自動生成。
@EqualsAndHashCode(of = "id")
@Data
class User { Long id; String name; }
new ArrayList<>(new HashSet<>(list))new ArrayList<>(new LinkedHashSet<>(list))list.stream().distinct().collect(toList())選對去重方式,程式碼既簡潔又高效。