Mon but est de filtrer pour une meilleure correspondance. Dans mon exemple, j'ai une liste de personnes que je souhaite filtrer par nom et prénom.
La prescendance correspondante serait:
Mon code jusqu'ici:
final List<Person> persons = Arrays.asList(
new Person("Doe", "John"),
new Person("Doe", "Jane"),
new Person("Munster", "Herman");
Person person = persons.stream().filter(p -> p.getSurname().equals("Doe")).???
En supposant que Person implémente equals et hashCode:
Person personToFind = new Person("Doe", "Jane");
Person person = persons.stream()
.filter(p -> p.equals(personToFind))
.findFirst()
.orElseGet(() ->
persons.stream()
.filter(p -> p.getSurname().equals(personToFind.getSurname()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Could not find person ..."))
);
Vous pouvez utiliser
Person person = persons.stream()
.filter(p -> p.getSurName().equals("Doe"))
.max(Comparator.comparing(p -> p.getFirstName().equals("Jane")))
.orElse(null);
Seuls les éléments portant le nom de famille correct seront pris en compte et le meilleur élément sera renvoyé, à savoir celui dont le prénom correspond. Sinon, le premier élément correspondant est renvoyé.
Comme déjà mentionné dans un commentaire , une boucle for
pourrait être plus efficace s'il existe un meilleur élément, car elle peut court-circuiter. S'il n'y a pas de meilleur élément avec le nom et le prénom correspondants, tous les éléments doivent être vérifiés dans toutes les implémentations.
Je proposerais ceci:
Optional<Person> bestMatch = persons.stream()
.filter(p -> "Doe".equals(p.getSurname()))
.reduce((person, person2) -> {
if ("John".equals(person.getFirstName())) {
return person;
} else if ("John".equals(person2.getFirstName())) {
return person2;
}
return person;
});
Person result = bestMatch.orElseThrow(IllegalArgumentException::new);
Le bon outil est .findFirst()
. Vous pouvez également utiliser .limit(1)
.