Java 8 Stream API для поиска уникального объекта, сопоставляющего значение свойства
Найдите совпадение объектов с значением свойства из коллекции с использованием потока Java 8.
List<Person> objects = new ArrayList<>();
Личные атрибуты → Имя, Телефон, Электронная почта.
Итерации по списку лиц и поиск подходящего адреса электронной почты.
Видел, что это можно сделать через поток Java 8 легко. Но это все равно вернет коллекцию?
Пример:
List<Person> matchingObjects = objects.stream.
filter(p -> p.email().equals("testemail")).
collect(Collectors.toList());
Но я знаю, что он всегда будет иметь один уникальный объект. Можем ли мы что-то сделать вместо Collectors.toList
, чтобы я получил фактический объект напрямую. Вместо получения списка объектов.
Ответы
Ответ 1
Вместо использования коллектора попробуйте использовать findFirst
или findAny
.
Optional<Person> matchingObject = objects.stream().
filter(p -> p.email().equals("testemail")).
findFirst();
Это возвращает Optional
, так как список может не содержать этот объект.
Если вы уверены, что в списке всегда есть этот человек, вы можете позвонить:
Person person = matchingObject.get();
Будьте осторожны! get
выдает NoSuchElementException
, если значение отсутствует. Поэтому настоятельно рекомендуется сначала убедиться, что значение присутствует (либо с isPresent
, либо лучше, используйте ifPresent
, map
, orElse
или любую другую альтернативу, найденную в классе Optional
).
Если вы согласны с ссылкой null
, если такого человека нет, то:
Person person = matchingObject.orElse(null);
Если возможно, я бы старался избегать использования эталонного маршрута null
. Другие альтернативные методы в классе Optional (ifPresent
, map
и т.д.) Могут решить множество вариантов использования. Я обнаружил, что использую orElse(null)
только тогда, когда у меня есть существующий код, который был разработан для приема ссылок null
в некоторых случаях.
У опциональных есть и другие полезные методы. Взгляните на дополнительный Javadoc.
Ответ 2
findAny
& orElse
Используя findAny()
и orElse()
:
Person matchingObject = objects.stream().
filter(p -> p.email().equals("testemail")).
findAny().orElse(null);
Останавливает поиск после обнаружения происшествия.
findAny
Optional<T> findAny()
Возвращает Optional, описывающий некоторый элемент потока, или пустой Optional, если поток пуст. Это операция короткого замыкания терминала. Поведение этой операции явно недетерминировано; Вы можете выбрать любой элемент в потоке. Это позволяет обеспечить максимальную производительность при параллельных операциях; цена заключается в том, что несколько вызовов одного и того же источника могут не возвращать один и тот же результат. (Если требуется стабильный результат, используйте вместо него findFirst().)
Ответ 3
Guava API предоставляет MoreCollectors.onlyElement(), который является сборщиком, который принимает поток , содержащий ровно один элемент, и возвращает этот элемент.
Возвращенный коллектор выбрасывает IllegalArgumentException
, если поток состоит из двух или более элементов, и NoSuchElementException
, если поток пуст.
Используйте приведенный ниже код для использования:
import static com.google.common.collect.MoreCollectors.onlyElement;
Person matchingPerson = objects.stream
.filter(p -> p.email().equals("testemail"))
.collect(onlyElement());