考虑到我有一个这样的Person对象列表:
Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}
使用java8流,如何仅通过fullName和职业属性获得重复对象的列表?
答案 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);