Карта потока возвращает ноль вместо потока

Имеется список элементов класса Event.

@Data
@AllArgsConstructor
public class Event {
    private Long id;
    private String nameRu;
    private String nameEn;
}

Я хочу получить значение одного поля из события (любого из объектов).

Event event1 = new Event(1, null, null);
Event event2 = new Event(2, null, null);
List<Event> events = new ArrayList<>();
events.add(event1);
events.add(event2);
int languageId = 1;

String name = events.stream().map(s -> {
                if (languageId == 1)
                    return s.getNameEn();
                else if (languageId == 2)
                    return s.getNameRu();
                else return s.getNameEn();
            }).findAny().orElse(null);

Но если в каждом элементе это поле имеет значение null, то функцияstream.map() возвращает значение null (но она должна возвращать поток с некоторым количеством значений null), а вызов findAny() выдает исключение NullPointerException.

Два вопроса:

  1. Почему карта() не возвращает поток, если карта() не является терминалом?
  2. Как я могу получить значение поля без исключений?

ну, вы видели это "orElse(null);" часть? Кроме того, вы заметили, что вы ввели ноль для каждого отдельного варианта языка?

Stultuske 13.06.2024 13:46

Пожалуйста, прочитайте документацию по findAny() docs.oracle.com/javase/8/docs/api/java/util/stream/… Особенно строку NullPointerException - if the element selected is null

Daria Pydorenko 13.06.2024 13:51

это не map(), возвращающий ноль! findAny(), как описано в , выдаст исключение NullPointerException, если выбранный элемент null (что, очевидно, имеет место, поскольку Event создаются со строками null) - трассировка стека должна ясно показывать, что findAny действительно выполняется

user85421 13.06.2024 13:51

Зачем вы проверяете languageId == 1, когда все, что вы делаете, — это то же самое, что и запасной вариант? Просто .map(s -> languageId == 2? s.getNameRu(): s.getNameEn()) сделает то же самое.

Holger 13.06.2024 14:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
4
81
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Согласно JavaDoc это ожидаемое поведение:

    /**
     * Returns an {@link Optional} describing some element of the stream, or an
     * empty {@code Optional} if the stream is empty.
     *
     * <p>This is a <a href = "package-summary.html#StreamOps">short-circuiting
     * terminal operation</a>.
     *
     * <p>The behavior of this operation is explicitly nondeterministic; it is
     * free to select any element in the stream.  This is to allow for maximal
     * performance in parallel operations; the cost is that multiple invocations
     * on the same source may not return the same result.  (If a stable result
     * is desired, use {@link #findFirst()} instead.)
     *
     * @return an {@code Optional} describing some element of this stream, or an
     * empty {@code Optional} if the stream is empty
     * @throws NullPointerException if the element selected is null
     * @see #findFirst()
     */
    Optional<T> findAny();

@throws NullPointerException if the element selected is null

Чтобы это исправить, вы должны отфильтровать нулевые элементы следующим образом:

        .map(s -> ... )
        .filter(Objects::nonNull)
        .findAny()
        .orElse(null);
  1. Почему карта() не возвращает поток, если карта() не является терминалом?

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

map() возвращает поток, но вы использовали .findAny(), который дает вам NPE.

  1. Как я могу получить значение поля без исключений?

Вы можете применить фильтр перед .findAny(), который удалит все нулевые значения,

Optional<String> name = events.stream().map(s -> {
            if (languageId == 1)
                return s.getNameEn();
            else if (languageId == 2)
                return s.getNameRu();
            else return s.getNameEn();
        })
        .filter(Objects::nonNull)
        .findAny();

Другие вопросы по теме