Optional.stream()

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

На этой неделе я узнал об одной интересной "новой" возможности Optional, о которой хочу рассказать в этом посте. Она доступна с Java 9, так что новизна ее относительна.

Давайте начнем со следующей последовательности для вычисления общей цены заказа:

public BigDecimal getOrderPrice(Long orderId) {
    List<OrderLine> lines = orderRepository.findByOrderId(orderId);
    BigDecimal price = BigDecimal.ZERO;       
    for (OrderLine line : lines) {
        price = price.add(line.getPrice());   
    }
    return price;
}
  • Предоставьте переменную-аккумулятор для цены

  • Добавьте цену каждой строки к общей цене

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

public BigDecimal getOrderPrice(Long orderId) {
    List<OrderLine> lines = orderRepository.findByOrderId(orderId);
    return lines.stream()
                .map(OrderLine::getPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
}

Давайте сосредоточимся на переменной orderId : она может содержать null.

Императивный способ обработки null заключается в том, чтобы проверить его в начале метода - и в конечном итоге сбросить:

public BigDecimal getOrderPrice(Long orderId) {
    if (orderId == null) {
        throw new IllegalArgumentException("Order ID cannot be null");
    }
    List<OrderLine> lines = orderRepository.findByOrderId(orderId);
    return lines.stream()
                .map(OrderLine::getPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
}

Функциональный способ заключается в том, чтобы обернуть orderId в Optional. Вот как выглядит код с использованием Optional:

public BigDecimal getOrderPrice(Long orderId) {
    return Optional.ofNullable(orderId)                            
            .map(orderRepository::findByOrderId)                   
            .flatMap(lines -> {                                    
                BigDecimal sum = lines.stream()
                        .map(OrderLine::getPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                return Optional.of(sum);                           
            }).orElse(BigDecimal.ZERO);                            
}
  1. Оберните orderId в Optional

  2. Найдите соответствующие строки заказа

  3. Используйте flatMap(), чтобы получить Optional<BigDecimal>; map() получит Optional<Optional<BigDecimal>>

  4. Нам нужно обернуть результат в Optional, чтобы он соответствовал сигнатуре метода.

  5. Если Optional не содержит значения, сумма равна 0

Optional делает код менее читабельным! Я считаю, что понятность должна быть всегда важнее стиля кода.

К счастью, Optional предлагает метод 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);
}

Вот краткая информация о типе на каждой строке:

Функциональный код не обязательно означает то, что это также читаемый код. Учитывая последние изменения, я считаю, что это и то, и другое.


Перевод материала подготовлен в рамках курса "Java Developer. Basic". Приглашаем всех желающих на день открытых дверей онлайн, где можно подробнее узнать о формате и программе обучения, а также познакомиться с преподавателем.

Источник: https://habr.com/ru/company/otus/blog/561730/


Интересные статьи

Интересные статьи

Привет, друзья! Меня зовут Петр, я представитель малого белорусского бизнеса со штатом чуть более 20 сотрудников. В данной статье хочу поделиться негативным опытом покупки 1С-Битрикс. ...
Приветствую вас (лично вас, а не всех кто это читает)! Сегодня мы: Создадим приложение (навык) Алисы с использованием нового (октябрь 2019) сервиса Yandex Cloud Functions. Настроим н...
В интернет-магазинах, в том числе сделанных на готовых решениях 1C-Битрикс, часто неправильно реализован функционал быстрого заказа «Купить в 1 клик».
Здравствуйте. Я уже давно не пишу на php, но то и дело натыкаюсь на интернет-магазины на системе управления сайтами Битрикс. И я вспоминаю о своих исследованиях. Битрикс не любят примерно так,...
Довольно часто владельцы сайтов просят поставить на свои проекты индикаторы курсов валют и их динамику. Можно воспользоваться готовыми информерами, но они не всегда позволяют должным образом настроить...