Нахождение дублированных объектов по двум свойствам - PullRequest
0 голосов
/ 15 ноября 2018

Учитывая, что у меня есть список объектов Person, подобных этому:

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

Используя потоки java8, как я могу получить список дублированных объектов только по свойству fullName и занятию?

Ответы [ 4 ]

0 голосов
/ 15 ноября 2018

Используя 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());
0 голосов
/ 15 ноября 2018

Мне нужно выяснить, были ли они дубликатами в паре 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.

0 голосов
/ 15 ноября 2018

Предлагаю решение со 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);
0 голосов
/ 15 ноября 2018

Сначала реализуйте equals и hashCode в своем классе person, а затем используйте.

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 в предикате фильтра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...