通过两个属性查找重复的对象

时间:2018-11-15 07:17:30

标签: java java-8

考虑到我有一个这样的Person对象列表:

Class Person {
  String fullName;
  String occupation;
  String hobby;
  int salary;
}

使用java8流,如何仅通过fullName和职业属性获得重复对象的列表?

4 个答案:

答案 0 :(得分:3)

通过在名字和职业上使用java-8 Stream()Collectors.groupingBy()

List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
    .values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());

答案 1 :(得分:2)

  

我需要确定它们是否是fullName-职业对中的任何重复

基于此评论,您似乎并不真的在乎哪个Person对象是重复的,而是有什么对象。

在这种情况下,您可以使用有状态的anyMatch

Collection<Person> input = new ArrayList<>();

Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
                        .anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));

您可以将List用作包含您已经看到的fullName + occupation组合的集合的“键”。如果再次看到此组合,则您将立即返回true,否则完成对元素的迭代并返回false

答案 2 :(得分:1)

首先在您的person类中实现equals和hashCode,然后使用。

List<Person> personList = new ArrayList<>();

Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
                .collect(Collectors.toSet());

如果对象大于2,则在过滤谓词中使用Collections.frequency(personList, p) >1

答案 3 :(得分:1)

我提供的解决方案复杂度为 O(n)。我提议使用Map按键(全名+职业)对给定列表进行分组,然后检索重复项。

public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
    Map<String, List<Person>> map = persons.stream()
                                           .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

    return map.values().stream()
              .filter(personList -> personList.size() > 1)
              .flatMap(List::stream)
              .collect(Collectors.toList());
}

客户代码:

List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);