Java 8 根据对象属性去重

在实际的开发过程中,我们经常会遇到需要对一个集合中的对象进行去重的需求。常见的做法是使用Set集合来保存唯一的对象,但这种方式对于复杂对象来说并不适用。在Java 8中,我们可以利用新的特性来根据对象的属性进行去重操作,本文将介绍如何使用Java 8实现根据对象属性去重。

问题背景

假设我们有一个类Person,它有两个属性nameage。我们需要从一个包含多个Person对象的集合中,根据name属性去重。

public class Person {
    private String name;
    private int age;

    // 省略构造方法和getter/setter
}

下面是一个示例的Person对象集合:

List<Person> persons = Arrays.asList(
    new Person("Alice", 20),
    new Person("Bob", 25),
    new Person("Alice", 30),
    new Person("Bob", 35)
);

我们希望得到一个去重后的集合,只包含唯一的Person对象,其中name属性相同的对象只保留一个。

传统的去重方法

在Java 8之前,我们通常会使用Set来实现对集合中对象的去重操作。但这种方式对于复杂对象来说并不适用,因为它是基于对象的hashCode()equals()方法来判断对象是否相等的。如果我们不重写这两个方法,那么Set会根据对象的引用来判断对象是否相等,而不是根据对象的属性。

为了使Set能够正确地去重,我们需要重写Person类的hashCode()equals()方法:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    result = prime * result + age;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    if (age != other.age)
        return false;
    return true;
}

然后我们可以通过以下方式进行去重操作:

Set<Person> uniquePersons = new HashSet<>(persons);

这样,我们就得到了一个去重后的Set集合。

Java 8的新特性

在Java 8中,我们可以使用新的特性来根据对象的属性进行去重操作,而无需重写hashCode()equals()方法。以下是具体步骤:

  1. 使用Stream将集合转换为流
  2. 使用distinct()方法去除重复的元素
  3. 使用collect()方法将流转换为集合

下面是具体的代码示例:

List<Person> uniquePersons = persons.stream()
    .distinct()
    .collect(Collectors.toList());

这样,我们就得到了一个根据name属性去重后的List集合。

示例代码

下面是完整的示例代码:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
            new Person("Alice", 20),
            new Person("Bob", 25),
            new Person("Alice", 30),
            new Person("Bob", 35)
        );

        List<Person> uniquePersons = persons.stream()
            .distinct()
            .collect(Collectors.toList());

        uniquePersons.forEach(System.out::println);
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name +