BOOKJAVA Telegram 3836
Optional.stream() появился в Java 9 и позволяет превратить Optional<T> в Stream<T> длины 0 или 1. Зачем это нужно?

📌 Когда применять?

◾️ 🧠 Интеграция с цепочками Stream API: если у вас есть коллекция Optional<T>, можно собрать все непустые значения без дополнительных проверок:


List<Optional<User>> userOptionals = …;
List<User> users = userOptionals.stream()
.flatMap(Optional::stream) // из каждого Optional либо 1 элемент, либо пусто
.collect(Collectors.toList());


Без Optional.stream() пришлось бы делать что-то вроде filter(Optional::isPresent).map(Optional::get).

◾️ 🧠 При операциях над вложенными опционалами: когда в потоке у вас Optional<Something> и вы хотите «сливать», а не оставлять пустые обёртки.

💡 Совет:

Если вы строите конвейер обработки данных, а на каком-то шаге может не быть значения — Optional.stream() поможет аккуратно пропустить «пустышки» и не ломать последующие операции.


⚠️ Но вот в чём «подводные камни» и почему нельзя злоупотреблять:

1. Потеря явности

◾️ Когда вы где-то просто хотите проверить: есть ли значение в Optional, — использование stream() создаёт впечатление, что у вас реально коллекция элементов, хотя всего лишь 1 или 0. Для простых случаев ifPresent(), map(), orElse() читается понятнее.


// Менее канонично:
optionalValue.stream().forEach(v -> doSomething(v));
// Лучше:
optionalValue.ifPresent(v -> doSomething(v));


2. Ненужные накладные расходы

◾️ Каждый вызов Optional.stream() создаёт объект стрима и небольшую внутреннюю структуру, что на горячем участке кода (в tight loop) может сказаться на производительности. Если вместо него можно обойтись map().orElse(), задумайтесь о легковесном варианте.

3. Скрытые баги

◾️ Если вы по ошибке используете Optional.stream() в одиночном случае (не в контексте объединения множества опционалов), код может стать менее очевидным. Например:


// Что тут происходит?
Stream.of(opt1, opt2, opt3)
.flatMap(Optional::stream)
.findFirst();


Казалось бы, надо искать первый непустой, но читающий код может не сразу понять логику: а вдруг нужно просто взять любое значение, а не первой в списке? Лушче явно:


Optional<User> result = opt1.isPresent() ? opt1
: opt2.isPresent() ? opt2
: opt3;


4. Лишняя сложность

◾️ В ситуациях, когда Optional появляется из map/filter в одном стриме, а потом вы вновь оборачиваете результат в Optional, лучше сразу строить последовательность через flatMap и filter без промежуточных Optional.

💡 Пример «полезного» применения:


List<Order> orders = getOrders();

// Для каждого заказа пытаемся получить пользователя из БД,
// но он может быть не найден (Optional<User>).
List<Optional<User>> maybeUsers = orders.stream()
.map(o -> userRepository.findById(o.getUserId()))
.toList();

// Теперь формируем список уже «существующих» юзеров:
List<User> users = maybeUsers.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());


Здесь Optional.stream() полностью оправдан: сразу избавляемся от «пустых» опционалов.

💡 Анти-паттерн:

Не используйте Optional.stream() внутри метода, который ожидает ровно одно значение или бросает исключение, если опционал пуст.



// Плохо:
User user = optionalUser.stream()
.findFirst()
.orElseThrow(() -> new NotFoundException("User not found"));

// Лучше так:
User user = optionalUser
.orElseThrow(() -> new NotFoundException("User not found"));


В первом случае мы заводим стрим без смысла, во втором — прямой и понятный код.

Итого:

◾️ 🧠 Используйте Optional.stream() только когда действительно нужно объединить несколько Optional-ов в один Stream и пропустить пустые.
◾️ ⚠️ В одиночных сценариях проверки и извлечения значения он избыточен и даже снижает читабельность и производительность.

👉@BookJava
👍4🤡1



tgoop.com/BookJava/3836
Create:
Last Update:

Optional.stream() появился в Java 9 и позволяет превратить Optional<T> в Stream<T> длины 0 или 1. Зачем это нужно?

📌 Когда применять?

◾️ 🧠 Интеграция с цепочками Stream API: если у вас есть коллекция Optional<T>, можно собрать все непустые значения без дополнительных проверок:


List<Optional<User>> userOptionals = …;
List<User> users = userOptionals.stream()
.flatMap(Optional::stream) // из каждого Optional либо 1 элемент, либо пусто
.collect(Collectors.toList());


Без Optional.stream() пришлось бы делать что-то вроде filter(Optional::isPresent).map(Optional::get).

◾️ 🧠 При операциях над вложенными опционалами: когда в потоке у вас Optional<Something> и вы хотите «сливать», а не оставлять пустые обёртки.

💡 Совет:

Если вы строите конвейер обработки данных, а на каком-то шаге может не быть значения — Optional.stream() поможет аккуратно пропустить «пустышки» и не ломать последующие операции.


⚠️ Но вот в чём «подводные камни» и почему нельзя злоупотреблять:

1. Потеря явности

◾️ Когда вы где-то просто хотите проверить: есть ли значение в Optional, — использование stream() создаёт впечатление, что у вас реально коллекция элементов, хотя всего лишь 1 или 0. Для простых случаев ifPresent(), map(), orElse() читается понятнее.


// Менее канонично:
optionalValue.stream().forEach(v -> doSomething(v));
// Лучше:
optionalValue.ifPresent(v -> doSomething(v));


2. Ненужные накладные расходы

◾️ Каждый вызов Optional.stream() создаёт объект стрима и небольшую внутреннюю структуру, что на горячем участке кода (в tight loop) может сказаться на производительности. Если вместо него можно обойтись map().orElse(), задумайтесь о легковесном варианте.

3. Скрытые баги

◾️ Если вы по ошибке используете Optional.stream() в одиночном случае (не в контексте объединения множества опционалов), код может стать менее очевидным. Например:


// Что тут происходит?
Stream.of(opt1, opt2, opt3)
.flatMap(Optional::stream)
.findFirst();


Казалось бы, надо искать первый непустой, но читающий код может не сразу понять логику: а вдруг нужно просто взять любое значение, а не первой в списке? Лушче явно:


Optional<User> result = opt1.isPresent() ? opt1
: opt2.isPresent() ? opt2
: opt3;


4. Лишняя сложность

◾️ В ситуациях, когда Optional появляется из map/filter в одном стриме, а потом вы вновь оборачиваете результат в Optional, лучше сразу строить последовательность через flatMap и filter без промежуточных Optional.

💡 Пример «полезного» применения:


List<Order> orders = getOrders();

// Для каждого заказа пытаемся получить пользователя из БД,
// но он может быть не найден (Optional<User>).
List<Optional<User>> maybeUsers = orders.stream()
.map(o -> userRepository.findById(o.getUserId()))
.toList();

// Теперь формируем список уже «существующих» юзеров:
List<User> users = maybeUsers.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());


Здесь Optional.stream() полностью оправдан: сразу избавляемся от «пустых» опционалов.

💡 Анти-паттерн:

Не используйте Optional.stream() внутри метода, который ожидает ровно одно значение или бросает исключение, если опционал пуст.



// Плохо:
User user = optionalUser.stream()
.findFirst()
.orElseThrow(() -> new NotFoundException("User not found"));

// Лучше так:
User user = optionalUser
.orElseThrow(() -> new NotFoundException("User not found"));


В первом случае мы заводим стрим без смысла, во втором — прямой и понятный код.

Итого:

◾️ 🧠 Используйте Optional.stream() только когда действительно нужно объединить несколько Optional-ов в один Stream и пропустить пустые.
◾️ ⚠️ В одиночных сценариях проверки и извлечения значения он избыточен и даже снижает читабельность и производительность.

👉@BookJava

BY Библиотека Java разработчика


Share with your friend now:
tgoop.com/BookJava/3836

View MORE
Open in Telegram


Telegram News

Date: |

Done! Now you’re the proud owner of a Telegram channel. The next step is to set up and customize your channel. Telegram channels fall into two types: The channel also called on people to turn out for illegal assemblies and listed the things that participants should bring along with them, showing prior planning was in the works for riots. The messages also incited people to hurl toxic gas bombs at police and MTR stations, he added. During the meeting with TSE Minister Edson Fachin, Perekopsky also mentioned the TSE channel on the platform as one of the firm's key success stories. Launched as part of the company's commitments to tackle the spread of fake news in Brazil, the verified channel has attracted more than 184,000 members in less than a month. The administrator of a telegram group, "Suck Channel," was sentenced to six years and six months in prison for seven counts of incitement yesterday.
from us


Telegram Библиотека Java разработчика
FROM American