На этой неделе я узнал об отличной “новой” функции Необязательный этим я хочу поделиться в этом посте. Он доступен с Java 9, так что его новизна относительна.
Давайте начнем со следующей последовательности, чтобы вычислить общую цену заказа:
public BigDecimal getOrderPrice(Long orderId) {
List lines = orderRepository.findByOrderId(orderId);
BigDecimal price = BigDecimal.ZERO; // 1
for (OrderLine line : lines) {
price = price.add(line.getPrice()); // 2
}
return price;
}
- Укажите переменную аккумулятора для цены
- Добавьте цену каждой строки к общей цене
В настоящее время, вероятно, более целесообразно использовать потоки вместо итераций. Следующий фрагмент эквивалентен предыдущему:
public BigDecimal getOrderPrice(Long orderId) {
List lines = orderRepository.findByOrderId(orderId);
return lines.stream()
.map(OrderLine::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
Давайте сосредоточимся на переменной OrderID : она может быть нулевой .
Обязательный способ обработки нулевых значений – проверить его в начале метода и в конечном итоге выбросить:
public BigDecimal getOrderPrice(Long orderId) {
if (orderId == null) {
throw new IllegalArgumentException("Order ID cannot be null");
}
List lines = orderRepository.findByOrderId(orderId);
return lines.stream()
.map(OrderLine::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
Функциональный способ состоит в том, чтобы обернуть упорядоченный в Необязательный . Вот как выглядит код с использованием Необязательно :
public BigDecimal getOrderPrice(Long orderId) {
return Optional.ofNullable(orderId) // 1
.map(orderRepository::findByOrderId) // 2
.flatMap(lines -> { // 3
BigDecimal sum = lines.stream()
.map(OrderLine::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
return Optional.of(sum); // 4
}).orElse(BigDecimal.ZERO); // 5
}
- Оберните
заказанныйвНеобязательном - Найдите соответствующие строки заказа
- Используйте
flatMap(), чтобы получитьНеобязательный<Большой десятичный>;map()получитНеобязательный<Необязательный<Большой десятичный>> - Нам нужно обернуть результат в
Необязательный, чтобы соответствовать сигнатуре метода - Если
Необязательныйне содержит значения, сумма равна0
Необязательно делает код менее читабельным! Я считаю, что читабельность должна превосходить стиль кода каждый раз.
К счастью, Необязательно предлагает метод stream() (начиная с Java 9). Это позволяет упростить функциональный конвейер:
public BigDecimal getOrderPrice(Long orderId) {
return Optional.ofNullable(orderId)
.stream()
.map(orderRepository::findByOrderId)
.flatMap(Collection::stream)
.map(OrderLine::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
Вот краткое описание типа в каждой строке:
| Необязательный | Необязательно.Может быть отменено (заказано) |
| Течение | поток() |
| Поток> | карта(местоположение заказа::найти идентификатор заказа) |
| Течение | Плоская карта(Коллекция::поток) |
| Течение | карта(Строка заказа::получить цену) |
| Большой десятичный | уменьшить(BigDecimal. НОЛЬ, десятичное число::добавить) |
Функциональный код не обязательно означает читаемый код. С последними изменениями я полагаю, что это и то, и другое.
Идти дальше:
Первоначально опубликовано на Фанат Java 21 февраля ул 2021
Оригинал: “https://dev.to/nfrankel/optional-stream-38ac”