如何使用java 8流获取列表中的所有不同对象?它必须将对象的所有字段相互比较。例如
Person a = Person("nameA", "35")
和
Person b = Person("nameA", "35")
应该是平等的。
我试图personList.stream().distinct().collect(Collectors.toList())
返回的是一个包含2个人的列表,而不仅仅是1个。
答案 0 :(得分:1)
您需要覆盖equals
和hashcode
才能获得预期的结果。
示例:
class Person {
private String name;
private String theOtherField;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return (name != null ? name.equals(person.name) : person.name == null) &&
(theOtherField != null ? theOtherField.equals(person.theOtherField) :
person.theOtherField == null);
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (theOtherField != null ? theOtherField.hashCode() : 0);
return result;
}
public Person(String name, String theOtherField) {
this.name = name;
this.theOtherField = theOtherField;
}
}
现在,假设您有一个这样的人员列表,例如:
List<Person> personList = Arrays.asList(new Person("nameA", "35"),
new Person("nameA", "35"));
执行distinct
操作应该会产生一个包含一个元素的列表。
List<Person> distinctPeople =
personList.stream()
.distinct()
.collect(Collectors.toList());
或者您可以在不使用Set
的情况下收集到distinct
实施内容:
Set<Person> distinctPeople = new HashSet<>(personList);
请注意,我已经在Person
班theOtherField
中命名了其中一个属性,因为我不知道它是否代表了这个人的年龄与理想情况一个人的年龄应该是int
而不是String
。
答案 1 :(得分:-1)
如果您可以依赖equals
类的hashCode
和Person
类,如@Eran在评论中写的那样,那么您可以使用您的代码,它将完成工作如预期。如果由于某种原因无法更改Person
类,那么您需要使用&#34; group by&#34;并指定你的密钥。
以下是如何使用&#34; group by&#34;创建自己的分组键:
Person person1 = new Person("John", "Doe");
Person person2 = new Person("John", "Doe");
Person person3 = new Person("Mary", "Doe");
Person person4 = new Person("Mary", "Doe");
Person person5 = new Person("john", "Smith");
List<Person> persons = Arrays.asList(person1, person2, person3, person4, person5);
// Creates your own equality using "group by". Here we are using first and last name concatenation
final Map<String, List<Person>> collect = persons.stream()
.collect(Collectors.groupingBy(o -> o.getFirstName() + o.getLastName()));
// Get the values and extract the first element to build a distinct list.
final List<Person> collect1 = collect.values().stream().map(ps -> ps.get(0)).collect(Collectors.toList());
System.out.println(collect1.size());
打印出来:
3