Використовуючи нові потоки Java8 api для пошуку одного конкретного елемента в колекції, я пишу такий код:
String theFirstString = myCollection.stream()
.findFirst()
.get();
Тут IntelliJ попереджає, що get () викликається без перевірки спочатку isPresent ().
Однак цей код:
String theFirstString = myCollection.iterator().next();
... не дає попередження.
Чи є якась глибока різниця між двома методами, яка робить потоковий підхід певним чином "небезпечнішим", що важливо ніколи не викликати get (), не викликаючи спочатку isPresent ()? Гуляючи навколо, я знаходжу статті, які розповідають про те, як програмісти недбало ставляться до необов’язкових <> і припускаю, що вони можуть викликати get () щоразу.
Справа в тому, що мені подобається, щоб виняток було кинуто на мене якомога ближче до місця, де мій код баггі, який у такому випадку був би там, де я дзвоню get (), коли не знайдено жодного елемента. Мені не хочеться писати марні нариси, такі як:
Optional<String> firstStream = myCollection.stream()
.findFirst();
if (!firstStream.isPresent()) {
throw new IllegalStateException("There is no first string even though I totally expected there to be! <sarcasm>This exception is much more useful than NoSuchElementException</sarcasm>");
}
String theFirstString = firstStream.get();
... хіба є якась небезпека спровокувати винятки з get (), про які я не знаю?
Прочитавши відповідь Карла Білефельдта та коментар Халка, я зрозумів, що мій код виключення був трохи незграбним, ось щось краще:
String errorString = "There is no first string even though I totally expected there to be! <sarcasm>This exception is much more useful than NoSuchElementException</sarcasm>";
String firstString = myCollection.stream()
.findFirst()
.orElseThrow(() -> new IllegalStateException(errorString));
Це виглядає корисніше і, мабуть, стане природним у багатьох місцях. Я все ще відчуваю, що мені захочеться вибрати один елемент зі списку, не маючи справи з усім цим, але це могло просто так, що мені потрібно звикнути до подібних конструкцій.