Java 8 Stream API, aby znaleźć unikalny obiekt pasujący do wartości właściwości

Znajdź obiekt pasujący do wartości właściwości z kolekcji za pomocą Java 8 Stream.

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

Atrybuty Osoby - > Imię, telefon, Email.

Iteracja poprzez listę osób i znaleźć obiekt pasujący e-mail. Widziałem, że można to zrobić za pomocą strumienia Java 8 łatwo. Ale to i tak zwróci kolekcję?

Ex:

List<Person> matchingObjects = objects.stream.
    filter(p -> p.email().equals("testemail")).
    collect(Collectors.toList());
Ale wiem, że zawsze będzie miał JEDEN unikalny przedmiot. Czy możemy zrobić coś zamiast Collectors.toList tak, że mam rzeczywiste obiekt bezpośrednio.Zamiast otrzymywać listę obiektów.
Author: Ushani, 2015-11-30

3 answers

Zamiast używać kolektora spróbuj użyć findFirst lub findAny.

Optional<Person> matchingObject = objects.stream().
    filter(p -> p.email().equals("testemail")).
    findFirst();

Zwraca Optional, ponieważ lista może nie zawierać tego obiektu.

Jeśli jesteś pewien, że lista zawsze zawiera tę osobę, możesz zadzwonić:

Person person = matchingObject.get();

Bądź jednak ostrożny! get rzuca NoSuchElementException jeśli nie ma wartości. Dlatego zaleca się, aby najpierw upewnić się, że wartość jest obecna (albo z isPresent lub lepiej, Użyj ifPresent, map, orElse lub którąkolwiek z innych alternatyw Znalezione w klasie Optional).

Jeśli nie masz nic przeciwko referencji null Jeśli nie ma takiej osoby, to:

Person person = matchingObject.orElse(null);

Jeśli to możliwe, starałbym się jednak unikać drogi odniesienia null. Inne metody alternatywne w klasie opcjonalnej (ifPresent, map itp.) może rozwiązać wiele przypadków użycia. Gdzie znalazłem się za pomocą orElse(null) jest tylko wtedy, gdy mam istniejący kod, który został zaprojektowany do przyjmowania null odniesienia w niektórych przypadkach.


Opcje mają inne użyteczne metody też. Spójrz na opcjonalny javadoc.

 136
Author: Indrek Ots,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-28 09:48:38

findAny & orElse

Za pomocą findAny() oraz orElse():

Person matchingObject = objects.stream().
filter(p -> p.email().equals("testemail")).
findAny().orElse(null);

Przestaje szukać po znalezieniu zdarzenia.

findAny

Optional<T> findAny()

Zwraca opcjonalny opisujący jakiś element strumienia lub opcjonalny pusty, jeśli strumień jest pusty. Jest to operacja zwarcia terminala. Zachowanie tej operacji jest jawnie nieeterministyczne; można dowolnie wybrać dowolny element w strumieniu. Ma to pozwolić na maksymalną wydajność w operacjach równoległych; koszt polega na tym, że wielokrotne wywołania na tym samym źródle mogą nie zwrócić tego samego wyniku. (Jeśli pożądany jest stabilny wynik, należy użyć funkcji findFirst ().)

 21
Author: Bijaya Bhaskar Swain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Guava API zapewnia Więcej kolektorów.onlyElement (), który jest kolektorem, który pobiera strumień zawierający dokładnie jeden element i zwraca ten element .

Zwracany kolektor rzuca an IllegalArgumentException jeśli strumień składa się z dwóch lub więcej elementów , a NoSuchElementException jeśli strumień jest pusty .

Patrz poniższy kod do użycia:

import static com.google.common.collect.MoreCollectors.onlyElement;

Person matchingPerson = objects.stream
                        .filter(p -> p.email().equals("testemail"))
                        .collect(onlyElement());
 9
Author: Sahil Chhabra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 02:46:03