Java8: поток findПервый результат

Я хочу знать, что есть способ избавиться от предупреждения в findFirst().get() без использования .orElse(), если я знаю, что каждый раз есть результат, поэтому я никогда не получаю NoSuchElementException. Например, см. Следующий код:

    List<String> myList = new ArrayList<>();
    myList.add("Test");
    myList.add("Example");
    myList.add("Sth");

    String fisrstString = myList.stream().findFirst().get(); // here I surely get "Test" 

Я не знаю, как это делают другие IDE, но моя IDE (IntelliJ) рассматривает это как предупреждение ('Optional.get()' without 'isPresent()'). Я думаю, вероятно, он не знает, когда вы можете получить NoSuchElementException там а когда нет, или я не знаю, почему. Я знаю, что есть способы решить это предупреждение (isPresent() check, .orElse(something)), но с бесполезным кодом, поэтому просто я не хочу использовать эти решения, потому что они так ненужным. Есть ли у вас какие-либо идеи, что я могу сделать или объяснить, как это обрабатывается theIDE?

Изменить: Извините за NPE, его NoSuchElementException У меня была эта ошибка, но я думаю, что вопрос по-прежнему доступен для него.

Ответ 1

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

String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);

Но это выглядит не очень хорошо. Вместо этого вы можете использовать профи функционального программирования и делать:

myList.stream().findFirst().ifPresent(service::doSomething);

Ответ 2

Сначала вы не получите NPE, но NoSuchElementException. Во-вторых, это вы, кто может быть уверен; но другие люди могут прийти и не осознают, что это не вызовет исключения.

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

И последнее: если вы так уверены, почему бы не выбрасывать исключение?

orElseThrow(IAmSureThisWillNotHappenException::new)

Ответ 3

Вы должны использовать Optional, возвращаемый findFirst(), вместо того, чтобы пытаться получить его значение (если оно действительно присутствует).

myList.stream()
    .findFirst()
    .ifPresent(/* consume the string here, if present */);

Optional.ifPresent получает Consumer, который будет использоваться, только если Optional содержит ненулевое значение.

Проблема заключается в том, что мы, разработчики Java, так привыкли к императивной парадигме... В частности, мы привыкли получать объект и нажимать, то есть на метод:

String myString = "hello"; // getting an object here

System.out.println(myString); // pushing the object to System.out here
                              // (via the println method)

С Optional, возвращаемым Stream.findFirst(), вы делали то же самое, что и выше:

String myString = myList.stream()
    .findFirst()
    .get(); // getting a string here

System.out.println(myString); // pushing the string here

С другой стороны, функциональная парадигма (включая Optional) обычно работает по-другому:

myList.stream()
    .findFirst()
    .ifPresent(myString -> System.out.println(myString));

Здесь вы не получаете строку, а затем нажимаете ее на какой-то метод. Вместо этого вы предоставляете аргумент для операции Optional ifPresent и позволяете реализации Optional вставлять значение в свой аргумент. Другими словами, вы вытащите значение, обернутое Optional с помощью аргумента ifPresent. ifPresent будет использовать этот аргумент Consumer, только если это значение присутствует.

Этот шаблон тяги очень часто встречается в функциональном программировании и очень полезен, как только вы привыкнете к нему. Это просто требует от разработчиков, чтобы начать думать (и программировать) по-другому.

Ответ 4

вы можете передать пустой список без проблем, но если вы попытаетесь получить 1-й элемент в пустом списке, вы получите NoSuchElementException

Stream API знает об этом безупречном, поэтому они предлагают вам несколько способов справиться с этим:

Option1: orElse вы можете вернуть значение по умолчанию, если не найден 1-й элемент

String firstString = myList.stream().findFirst().orElse("Ups!");

Option2: orElseGet вы можете использовать Supplier<String>, который возвращает строку, если не найден 1-й элемент

firstString = myList.stream().findFirst().orElseGet(mySupplier);

Option3: orElseThrow вы можете создать исключение, если не найден 1-й элемент

firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);

System.out.println(fisrstString);

Ответ 5

IF, вы знаете, что ваш Optional никогда не будет пустым, вы можете использовать аннотацию @SuppressWarnings, как показано ниже:

@SuppressWarnings("ConstantConditions") String foo = Optional.of("bar").get();

Иногда Optional.get будет поднимать NullPointerException, например:

Optional<String> it = Optional.empty();
String foo = it.get();
          //   ^--- throws NullPointerException when this method is invoked

SO, когда это выражение используется Intellij будет сообщать об обнаружении предупреждения.

IF вы хотите отключить всю проверку контрактов, вы можете сделать следующие действия: Настройки Инспекции → не отмечены Постоянное условие и исключения → не забудьте нажать кнопку Применить внизу, чтобы сохранить свои настройки.

IF вы не хотите отключать всю проверку контракта, кроме Optional.get() предупреждений, вы можете сделать следующие действия: Настройки Инспекции > → проверили условие Константа и исключения → в правой нижней части рамки для настройки Optional.get() предупреждений → не забудьте нажать Применить нажмите кнопку внизу для сохранения настроек.

введите описание изображения здесь