Рубрики
Без рубрики

Необязательно.поток()

На этой неделе я узнал об отличной “новой” функции Optional, которой я хочу поделиться в этом посте. Это… Помеченный как java, api, необязательный, функциональный.

На этой неделе я узнал об отличной “новой” функции Необязательный этим я хочу поделиться в этом посте. Он доступен с 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;
}
  1. Укажите переменную аккумулятора для цены
  2. Добавьте цену каждой строки к общей цене

В настоящее время, вероятно, более целесообразно использовать потоки вместо итераций. Следующий фрагмент эквивалентен предыдущему:

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
}
  1. Оберните заказанный в Необязательном
  2. Найдите соответствующие строки заказа
  3. Используйте flatMap() , чтобы получить Необязательный<Большой десятичный> ; map() получит Необязательный<Необязательный<Большой десятичный>>
  4. Нам нужно обернуть результат в Необязательный , чтобы соответствовать сигнатуре метода
  5. Если Необязательный не содержит значения, сумма равна 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”