在 Java 中,使用 Stream 流對自定義對象數組去重的核心是確保對象能正確判斷“重復”的邏輯。以下是具體實現方法及場景分析:
方法 1:直接使用 distinct()
(需重寫 equals
和 hashCode
)
若自定義對象已正確重寫 equals()
和 hashCode()
方法,可直接通過 distinct()
去重。
適用場景:對象的唯一性由所有字段共同決定(如數據庫實體類的主鍵)。
示例代碼
public class Person {private String id;private String name;// 構造方法、Getter/Setter 省略@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return Objects.equals(id, person.id); // 根據 id 判斷是否相等}@Overridepublic int hashCode() {return Objects.hash(id); // 基于 id 生成哈希}
}// 使用 Stream 去重
Person[] people = ...; // 自定義對象數組
List<Person> uniqueList = Arrays.stream(people).distinct().collect(Collectors.toList());
方法 2:基于對象的某個唯一屬性去重(無需重寫 equals
和 hashCode
)
若無法修改對象類(如第三方庫的類),或需根據部分字段去重,可用 Collectors.toMap
或 TreeSet
實現。
(1) 使用 Collectors.toMap
適用場景:根據唯一鍵(如 id
)去重,保留第一個出現的元素。
List<Person> uniqueList = Arrays.stream(people).collect(Collectors.toMap(Person::getId, // Key 提取函數(根據 id 去重)p -> p, // Value 為對象本身(existing, replacement) -> existing // 沖突時保留已存在的元素)).values() // 獲取去重后的 Value 集合.stream().collect(Collectors.toList());
(2) 使用 TreeSet
自定義比較器
適用場景:需要根據多個字段去重,或動態指定去重規則。
List<Person> uniqueList = Arrays.stream(people).collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(p -> p.getId() + p.getName())))).stream().collect(Collectors.toList());
方法 3:使用 filter
+ 內存狀態去重
適用場景:需根據動態條件去重(如去重后保留最后一個元素)。
(1) 使用 ConcurrentHashMap
維護狀態
Set<String> seenIds = ConcurrentHashMap.newKeySet();
List<Person> uniqueList = Arrays.stream(people).filter(p -> seenIds.add(p.getId())) // 若 id 未出現過,保留.collect(Collectors.toList());
(2) 保留最后一個出現的元素
List<Person> uniqueList = Arrays.stream(people).collect(Collectors.toMap(Person::getId,p -> p,(oldValue, newValue) -> newValue // 沖突時保留新元素)).values().stream().collect(Collectors.toList());
總結回答
- 直接去重:若對象重寫了
equals()
和hashCode()
,直接用distinct()
。 - 按屬性去重:使用
Collectors.toMap
或TreeSet
,根據唯一鍵(如id
)過濾。 - 動態去重:通過
filter
配合內存集合(如ConcurrentHashMap
)控制去重邏輯。
關鍵點:明確業務中“重復”的定義(如全字段相等或部分字段相等),選擇性能與代碼簡潔性兼顧的方案。