获取所有字段所不同的对象列表

时间:2018-04-08 09:28:13

标签: java java-stream

如何使用java 8流获取列表中的所有不同对象?它必须将对象的所有字段相互比较。例如

Person a = Person("nameA", "35")Person b = Person("nameA", "35")

应该是平等的。 我试图personList.stream().distinct().collect(Collectors.toList())返回的是一个包含2个人的列表,而不仅仅是1个。

2 个答案:

答案 0 :(得分:1)

您需要覆盖equalshashcode才能获得预期的结果。

示例:

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);

请注意,我已经在PersontheOtherField中命名了其中一个属性,因为我不知道它是否代表了这个人的年龄与理想情况一个人的年龄应该是int而不是String

答案 1 :(得分:-1)

如果您可以依赖equals类的hashCodePerson类,如@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