record Person(
int id, String name, String mother, LocalDate birth, int center) { }
List<Person> records = List.of(
new Person(1, "Antonio Carlos da Silva", "Ana da Silva", LocalDate.of(2008, 3, 31), 1),
new Person(2, "Carlos Roberto de Souza", "Amália Maria de Souza", LocalDate.of(2004, 12, 10), 1),
new Person(3, "Pedro de Albuquerque", "Maria de Albuquerque", LocalDate.of(2006, 4, 3), 2),
new Person(4, "Danilo da Silva Cardoso", "Sônia de Paula Cardoso", LocalDate.of(2002, 8, 10), 3),
new Person(5, "Ralfo dos Santos Filho", "Helena dos Santos", LocalDate.of(2012, 2, 21), 4),
new Person(6, "Pedro de Albuquerque", "Maria de Albuquerque", LocalDate.of(2006, 4, 3), 2),
new Person(7, "Antonio Carlos da Silva", "Ana da Silva", LocalDate.of(2008, 3, 31), 1),
new Person(8, "Paula Cristina de Abreu", "Cristina Pereira de Abreu", LocalDate.of(2014, 10, 25), 2),
new Person(9, "Rosana Pereira de Campos", "Ivana Maria de Campos", LocalDate.of(2002, 7, 16), 3),
new Person(10, "Pedro de Albuquerque", "Maria de Albuquerque", LocalDate.of(2006, 4, 3), 2)
);
record PersonKey(String name, String mother, LocalDate birth, int center) {
PersonKey(Person p) {
this(p.name(), p.mother(), p.birth(), p.center());
}
}
List<Person> result = records.stream()
.collect(Collectors.groupingBy(PersonKey::new))
.values()
.stream()
.filter(l -> l.size() > 1)
.flatMap(Collection::stream)
.sorted(Comparator.comparing(Person::center).thenComparing(Person::id))
.toList();
This approach collects the list to a Map<PersonKey, List<Person>>, where PersonKey are all the fields that are involved in the duplicate record check. Next, only the List<Person> values of this map are kept and are converted to a Stream<List<Person>>. Every element in this stream with at least two elements are kept (i.e. the ones that are duplicates). This is flattened into a Stream<Person>, and then sorted by center with id as the tie-breaker. Finally, the stream is collected into a List<Person>.