Java нуль-безопасные потоки из коллекций

1. Обзор

В этом руководстве мы увидим, как создавать нулевые безопасные потоки из коллекций Java.

Начнем с того, что для полного понимания этого материала требуется некоторое знакомство со ссылками на методы Java 8, лямбда-выражениями, Optional и Stream API.

Если вы не знакомы с какой-либо из этих тем, сначала просмотрите наши предыдущие статьи:

2. Maven Dependency

Прежде чем мы начнем, есть одна зависимость от Maven, которая нам понадобится для определенных сценариев:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.2</version>
</dependency>

Библиотека commons-collection4 библиотека можно загрузить с Maven Central.

3. Создание потоков из коллекций

Основной подход к созданию Stream из любого типа Collection заключается в вызове методов stream () или parallelStream () для коллекции в зависимости от тип потока, который требуется:

Collection<String> collection = Arrays.asList("a", "b", "c");
Stream<String> streamOfCollection = collection.stream();

Скорее всего, в какой-то момент наша коллекция будет иметь внешний источник, и при создании потоков из коллекций мы, вероятно, получим метод, аналогичный приведенному ниже.

public Stream<String> collectionAsStream(Collection<String> collection) {
    return collection.stream();
}

Это может вызвать некоторые проблемы. Когда предоставленная коллекция указывает на ссылку null , код генерирует исключение NullPointerException во время выполнения.

В следующем разделе рассматривается, как мы можем защитить от этого.

4. Создание созданных коллекционных потоков Null-Safe

4.1. Добавить проверки, чтобы предотвратить Null разыменования

Чтобы предотвратить непреднамеренные исключения null указателей, мы можем добавить проверки для предотвращения null ссылок при создании потоков из коллекций:

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

Этот метод, однако, имеет несколько проблем.

Во-первых, проверка null мешает бизнес-логике снизить общую читаемость программы.

Во-вторых, использование null для представления отсутствия значения считается неправильным подходом после Java SE 8: существует лучший способ для моделирования отсутствия и наличия значения.

Важно помнить, что пустая коллекция Collection - это не то же самое, что null Collection . В то время как первый указывает на то, что в нашем запросе нет результатов или элементов для отображения, второй указывает на то, что во время процесса произошла ошибка.

4.2. Использовать метод emptyIfNull из библиотеки CollectionUtils

Мы можем использовать CollectionUtils библиотеку Apache Commons, чтобы наш поток null был безопасным. Эта библиотека предоставляет метод emptyIfNull , который возвращает неизменяемую пустую коллекцию, заданную коллекцией null в качестве аргумента, или саму коллекцию в противном случае:

public Stream<String> collectionAsStream(Collection<String> collection) {
    return emptyIfNull(collection).stream();
}

Это очень простая стратегия для принятия. Однако это зависит от внешней библиотеки. Если политика разработки программного обеспечения ограничивает использование такой библиотеки, то это решение становится пустым и недействительным.

4.3. Используйте Java 8 Optional

Https://www.baeldung.com/java-optional[ Optional ]в Java SE 8 - это контейнер с одним значением, который либо содержит значение, либо его нет. Если значение отсутствует, контейнер Optional называется пустым.

Использование Optional можно считать лучшей общей стратегией для создания нулевой безопасной коллекции из потока.

Давайте посмотрим, как мы можем его использовать, а затем кратко обсудим ниже:

public Stream<String> collectionToStream(Collection<String> collection) {
    return Optional.ofNullable(collection)
      .map(Collection::stream)
      .orElseGet(Stream::empty);
}
  • Optional.ofNullable (collection) создает объект Optional из

Переданная коллекция. Пустой объект Optional создается, если Коллекция null. map (Collection :: stream) ** извлекает значение, содержащееся в

Optional объект в качестве аргумента для метода map ( Collection.stream () ) orElseGet (Stream :: empty) ** возвращает запасное значение в событии

что объект Optional пуст, т.е. переданная коллекция равна null .

В результате мы проактивно защищаем наш код от непреднамеренных исключений null указателя.

4.4. Используйте Java 9 Stream OfNullable

Изучение нашего предыдущего троичного примера в разделе 4.1. и учитывая возможность того, что некоторые элементы могут быть null вместо Collection , мы имеем в своем распоряжении метод ofNullable в классе Stream .

Мы можем преобразовать приведенный выше пример в:

Stream<String> collectionAsStream(Collection<String> collection) {
  return collection.stream().flatMap(s -> Stream.ofNullable(s));
}

5. Заключение

В этой статье мы кратко рассмотрели, как создать поток из данной коллекции. Затем мы приступили к изучению трех ключевых стратегий, обеспечивающих нулевую безопасность созданного потока при создании из коллекции.

Наконец, мы указали на слабость использования каждой стратегии, где это уместно.

Как обычно, полный исходный код, который сопровождает статью, доступен на GitHub over .