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

Java 通过两个属性查找重复对象,java,java-8,Java,Java 8,考虑到我有一个这样的Person对象列表: Class Person { String fullName; String occupation; String hobby; int salary; } 使用java8 streams,如何仅按fullName和occupation属性获取重复对象的列表 首先在person类中实现equals和hashCode,然后使用 List<Person> personList = new ArrayList<>()

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

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

使用java8 streams,如何仅按fullName和occupation属性获取重复对象的列表

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

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

Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
                .collect(Collectors.toSet());
List personList=new ArrayList();
设置重复项=personList.stream().filter(p->Collections.frequency(personList,p)==2)
.collect(收集器.toSet());
如果对象多于2个,则在筛选器谓词中使用
Collections.frequency(personList,p)>1

我需要找出它们是否是全名-职业对中的任何重复项,这必须是唯一的

基于此评论,您似乎并不真正关心复制了哪些
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)));
Collection input=new ArrayList();
Set seen=新的HashSet();
布尔hasDupes=input.stream()
.anyMatch(p->!seen.add(p.fullName,p.occulation)列表);

您可以使用
列表
作为包含您已经看到的
全名
+
职业
组合的集合的“键”。如果再次看到此组合,您将立即返回
true
,否则您将完成元素迭代并返回
false

我提供了具有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());
}
公共静态列表getDuplicates(列表人员、函数分类器){
Map=persons.stream()
.collect(Collectors.groupingBy(分类器,Collectors.mapping(Function.identity(),Collectors.toList()));
返回map.values().stream()
.filter(personList->personList.size()>1)
.flatMap(列表::流)
.collect(Collectors.toList());
}
客户端代码:

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

使用java-8
Stream()
收集器。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());
List 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());

在person类中添加equals和hashCode?您签出了吗?是的。我不需要区分重复项,而是需要找出它们是否是全名-职业对中的任何重复项,这必须是唯一的。我发现很多主题都删除了重复的内容。我需要添加它们。这是我的答案的副本,但我没有复制它,是我自己做的,并同时发布@oleg.cherednik。或者,您可以将
过滤器
平面图
步骤:
.flatMap(list->list.size()>1?list.stream():null)
。但不应强制键类型为
字符串
。通过字符串连接为两个属性创建键效率低下且容易出错(可能会在生成的字符串上产生冲突)。