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()
предупреждений → не забудьте нажать Применить нажмите кнопку внизу для сохранения настроек.
![введите описание изображения здесь]()