給定包含重復元素的 ArrayList,需保留首次出現順序並移除後續重復項。假設元素已正確重寫 equals() 和 hashCode()(如自定義 Person 類)。
public static <E> ArrayList<E> distinct(ArrayList<E> source) {
ArrayList<E> result = new ArrayList<>();
for (E elem : source) {
if (!result.contains(elem)) { // 依賴 equals 比較
result.add(elem);
}
}
return result;
}
ArrayList<Person> al = new ArrayList<>();
al.add(new Person("lisi1", 21));
al.add(new Person("lisi2", 22));
al.add(new Person("lisi3", 23));
al.add(new Person("lisi4", 24));
al.add(new Person("lisi2", 22)); // 重復
al.add(new Person("lisi3", 23)); // 重復
System.out.println("去重前:" + al);
al = distinct(al);
System.out.println("去重後:" + al);
// 驗證 remove 也基於 equals
System.out.println(al.remove(new Person("lisi2", 22))); // true
System.out.println("移除後:" + al);
| 方案 | 時間複雜度 | 順序保留 | 適用場景 |
|---|---|---|---|
| 雙層循環/contains | O(n²) | 是 | 小數據量(<1000) |
| LinkedHashSet | O(n) | 是 | 通用首選,需元素實現 hashCode/equals |
| Stream.distinct() | O(n) | 是 | JDK 8+ 函數式風格 |
| 排序後相鄰比較 | O(n log n) | 否 | 可排序對象,不要求順序 |
// 一行代碼,高效且保留順序
List<Person> distinct = list.stream().distinct().collect(Collectors.toList());
// 或使用 LinkedHashSet
List<Person> distinct = new ArrayList<>(new LinkedHashSet<>(list));
contains/remove 依賴 equals(),**務必正確重寫 equals 和 hashCode**,否則無法識別邏輯相等對象。new ArrayList<>(new LinkedHashSet<>(list)) 避免了擴容開銷,性能最優。