Java 8 根据对象属性去重
在实际的开发过程中,我们经常会遇到需要对一个集合中的对象进行去重的需求。常见的做法是使用Set
集合来保存唯一的对象,但这种方式对于复杂对象来说并不适用。在Java 8中,我们可以利用新的特性来根据对象的属性进行去重操作,本文将介绍如何使用Java 8实现根据对象属性去重。
问题背景
假设我们有一个类Person
,它有两个属性name
和age
。我们需要从一个包含多个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()
方法。以下是具体步骤:
- 使用
Stream
将集合转换为流 - 使用
distinct()
方法去除重复的元素 - 使用
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 +