You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:57:06