如何移除List中多属性匹配的重复元素?
移除List中多属性匹配的重复元素
需求:现有一个包含Person实例的List,Person类包含firstName、lastName和age三个属性。需要过滤掉firstName和lastName同时相同的重复实例(忽略age属性),每组唯一的姓名组合仅保留一个实例,具体保留哪一个不做要求。
示例代码
Person类
public class Person { private String firstName; private String lastName; private int age; public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } @Override public String toString() { return firstName + " " + lastName; } // 解决方案需要用到getter方法 public String getFirstName() { return firstName; } public String getLastName() { return lastName; } }
Main类(待完善)
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { Person p1 = new Person("Mike", "Doe", 25); Person p2 = new Person("Mike", "Doe", 54); Person p3 = new Person("John", "Doe", 61); Person p4 = new Person("Barry", "Adams", 61); List<Person> people = new ArrayList<>(); people.add(p1); people.add(p2); people.add(p3); people.add(p4); // 此处需要完善过滤逻辑 List<Person> uniquePeople = null; System.out.println(uniquePeople); } }
预期输出
[Mike Doe, John Doe, Barry Adams]
解决方案
方法1:Stream + LinkedHashSet(保留插入顺序)
通过自定义比较器将元素收集到LinkedHashSet中,利用集合的去重特性实现需求,同时保留原列表的插入顺序:
import java.util.stream.Collectors; import java.util.LinkedHashSet; // ... 其他代码 ... List<Person> uniquePeople = people.stream() .collect(Collectors.toCollection(() -> new LinkedHashSet<>( Comparator.comparing(p -> p.getFirstName() + "|" + p.getLastName()) )));
方法2:Stream + Filter + HashSet(轻量灵活)
用HashSet记录已经处理过的姓名组合,通过filter方法只保留首次出现的实例:
import java.util.HashSet; import java.util.stream.Collectors; // ... 其他代码 ... HashSet<String> seenNamePairs = new HashSet<>(); List<Person> uniquePeople = people.stream() .filter(person -> seenNamePairs.add(person.getFirstName() + "|" + person.getLastName())) .collect(Collectors.toList()); // Java 16+ 可直接用 .toList()
方法3:重写Person类的equals和hashCode(全局生效)
如果希望所有场景下都以姓名组合判断Person实例是否相等,可以修改Person类的equals和hashCode方法:
import java.util.Objects; // ... Person类其他代码 ... @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(firstName, person.firstName) && Objects.equals(lastName, person.lastName); } @Override public int hashCode() { return Objects.hash(firstName, lastName); }
之后直接通过LinkedHashSet去重并保留顺序:
List<Person> uniquePeople = new ArrayList<>(new LinkedHashSet<>(people));
注意:此方法会改变Person类的全局相等判断逻辑,可能影响其他使用该类的业务场景,需谨慎使用。
内容的提问来源于stack exchange,提问作者Sherbet Head
相关产品推荐
相关产品推荐

