Как лучше всего создать поток Java 8 из объекта с нулевым значением?
Каков наилучший/идиоматический способ выполнения нулевой проверки перед получением потока?
У меня есть метод, который получает List
который может быть нулевым. Поэтому я не могу просто вызвать .stream()
для переданного значения. Есть ли какой-то статический помощник, который дал бы мне пустой поток, если значение равно null?
Ответы
Ответ 1
Я согласен со Стюартом Марксом, что list == null? Stream.empty(): list.stream()
list == null? Stream.empty(): list.stream()
- это правильный способ сделать это (см. Его ответ) или, по крайней мере, правильный способ сделать это до Java 9 (см. Редактирование ниже), но я оставлю этот ответ до демонстрации использования Дополнительного API.
<T> Stream<T> getStream(List<T> list) {
return Optional.ofNullable(list).map(List::stream).orElseGet(Stream::empty);
}
Редактировать: Java 9 добавил статический фабричный метод Stream.<T>ofNullable(T)
, который возвращает пустой поток с null
аргументом, в противном случае поток с аргументом является единственным элементом. Если аргумент является коллекцией, мы можем затем использовать flatMap
чтобы превратить его в поток.
<T> Stream<T> fromNullableCollection(Collection<? extends T> collection) {
return Stream.ofNullable(collection).flatMap(Collection::stream);
}
Это не злоупотребляет дополнительным API, как обсуждалось Стюартом Марксом, и, в отличие от решения с троичными операторами, нет никакой возможности для исключения нулевого указателя (например, если вы не обращали внимания и испортили порядок операндов). Он также работает с подстановочным знаком с верхним ограничением без использования SuppressWarnings("unchecked")
благодаря сигнатуре flatMap
, так что вы можете получить Stream<T>
из коллекции элементов любого подтипа T
Ответ 2
Самое лучшее, что я могу думать о том, чтобы использовать Optional
с orElseGet
методом.
return Optional.ofNullable(userList)
.orElseGet(Collections::emptyList)
.stream()
.map(user -> user.getName())
.collect(toList());
Обновлено с помощью @Misha, чтобы использовать Collections::emptyList
ArrayList::new
Ответ 3
В других ответах экземпляр Optional
создается и используется строго в пределах одного и того же оператора. Optional
класс в первую очередь полезен для связи с вызывающим абонентом о наличии или отсутствии возвращаемого значения, слитого с фактическим значением, если оно присутствует. Использование его полностью в рамках одного метода кажется ненужным.
Позвольте мне предложить следующую прозаическую технику:
static <T> Stream<T> nullableListToStream(List<T> list) {
return list == null ? Stream.empty() : list.stream();
}
Я думаю, что тернарный оператор в наши дни несколько декален, но я думаю, что это самое простое и эффективное решение.
Если бы я писал это по-настоящему (то есть для реальной библиотеки, а не только для образца кода в Stack Overflow), я бы поставил подстановочные знаки, чтобы тип возвращаемого потока мог отличаться от типа List. О, и это может быть коллекция, так как там, где определяется метод stream()
:
@SuppressWarnings("unchecked")
static <T> Stream<T> nullableCollectionToStream(Collection<? extends T> coll) {
return coll == null ? Stream.empty() : (Stream<T>)coll.stream();
}
(Подавление предупреждений необходимо из-за того, что из Stream<? extends T>
в Stream<T>
это безопасно, но компилятор этого не знает).
Ответ 4
apache commons-collections4:
CollectionUtils.emptyIfNull(list).stream()
Ответ 5
Лично я считаю null устаревшим и использовать Необязательный, когда это возможно, несмотря на (незначительные) накладные расходы. Поэтому я использую интерфейс от Stuart Marks с реализацией на основе gdejohn, т.е.
@SuppressWarnings("unchecked")
static <T> Stream<T> nullableCollectionToStream(Collection<? extends T> coll)
{
return (Stream<T>) Optional.ofNullable(coll)
.map(Collection::stream)
.orElseGet(Stream::empty);
}