2017-01-11 2 views
17

Я ищу метод, который может создавать поток сбора, но является нулевым. Если коллекция null, возвращается пустой поток. Как это:Null safe Collection as Stream в Java 8

Utils.collectionAsStream(collection).filter(...); 

Я создал свой собственный метод:

public static <T> Stream<T> collectionAsStream(Collection<T> collection) { 
    if (collection == null) { 
     return Stream.empty(); 
    } 
    return collection.stream(); 
} 

Но мне интересно, если есть что-то вроде этого в стандартной версии JDK?

+6

Вы должны попытаться избежать 'null' коллекции в первую очередь. Лучшая практика - предпочесть использовать пустую коллекцию вместо этого. –

+2

Да, я согласен, но если вы зависите от чужой библиотеки, у вас нет выбора. – Gondy

+0

В этом случае вы можете просто заменить коллекцию, которую вы получаете из этой библиотеки, пустой, когда она вернет «null». Немного похоже на решение greg. –

ответ

19

Вы можете использовать org.apache.commons.collections4. CollectionUtils :: emptyIfNull:

org.apache.commons.collections4.CollectionUtils.emptyIfNull(list).stream().filter(...); 
+0

Мне действительно нравится это решение, потому что оно очень простое. Однако требуется внешняя библиотека, но в мире Maven и Gradle это не проблема. Я знаю, что я просил JDK8, но, похоже, ничего такого не было. – Gondy

22

Вы можете использовать Optional:

Optional.ofNullable(collection).orElse(Collections.emptySet()).stream()... 

Я выбрал Collections.emptySet() произвольно в качестве значения по умолчанию в случае collection равна нулю. Это приведет к вызову метода stream(), производящему пустой Stream, если collection имеет значение NULL.

Пример:

Collection<Integer> collection = Arrays.asList (1,2,3); 
System.out.println (Optional.ofNullable(collection).orElse(Collections.emptySet()).stream().count()); 
collection = null; 
System.out.println (Optional.ofNullable(collection).orElse(Collections.emptySet()).stream().count()); 

Выход:

3 
0 

Альтернативно, как marstran предложил, вы можете использовать:

Optional.ofNullable(collection).map(Collection::stream).orElse(Stream.empty())... 
+3

'Optional.ofNullable (collection) .map (Collection :: stream) .orElse (Stream.empty());' - возможное эквивалентное решение, в котором вам не нужно выбирать 'Collections.emptySet()'. – marstran

+5

Как упоминалось [@StuartMarks] (http://stackoverflow.com/users/1441122/stuart-marks) как _Use, Abstruse Use и Abuse_: [Правило № 4] (https://youtu.be/Ej0sss6cq14? t = 27m51s): _ Как правило, это плохая идея создать «Необязательный» для единственной цели из методов цепочки, чтобы получить значение_. –

+0

@DidierL Я не могу смотреть этот клип YouTube прямо сейчас, но первое впечатление о том, что я вообще не согласен. Сегодня я проверю его. Случай, который мы имеем здесь, выглядит довольно чистым: 'collection! = Null? collection.stream(): Stream.empty(); 'хотя. – marstran

1

Вы можете использовать что-то вроде этого:

public static void main(String [] args) { 
    List<String> someList = new ArrayList<>(); 
    asStream(someList).forEach(System.out::println); 
} 

public static <T> Stream<T> asStream(final Collection<T> collection) { 
    return Optional.ofNullable(collection) 
      .map(Collection::stream) 
      .orElseGet(Stream.empty()); 
} 
+0

еще лучше лениво оценить альтернативу, используя '.ORElseGet (Stream :: empty)'. –

+0

Да, это правда :) –

6

Ваш метод collectionAsStream() может быть упрощена до версии даже проще, чем при использовании Optional:

public static <T> Stream<T> collectionAsStream(Collection<T> collection) { 
    return collection == null ? Stream.empty() : collection.stream(); 
} 

Обратите внимание, что в большинстве случаев, это, вероятно, лучше просто проверить отсутствие ошибок до строительства трубопровода:

if (collection != null) { 
    collection.stream().filter(...) 
} // else do nothing 

То, что вы хотите, кажется полезным только тогда, когда вам нужно вернуть поток (в том числе для плоской карты) или, может быть, соединить его с другим.

1

Если загрузка библиотеки org.apache.commons.collections4 не является вариантом, вы можете просто написать свой собственный метод обертки/удобства.

public static <T> Stream<T> asStream(final Collection<T> collection) { 
    return collection == null ? (Stream<T>) Collections.emptyList().stream() 
           : collection.stream(); 
} 

Или упаковка коллекции с Optional.ofNullable

public static <T> Stream<T> asStream(final Collection<T> collection) { 
    return Optional.ofNullable(collection) 
      .orElse(Collections.emptySet()).stream(); 
}