Как отображать и суммировать элементы из списка в Java

Источник: DZone В этой публикации вы узнаете, как из списка в Java отобразить и суммировать количество элементов. Отображение элементов из списка (List) означает, что каждый элемент из этого списка будет преобразован в другой объект. Суммирование элементов из списка означает, что все элементы из этого списка будут объединены в один объект, который не обязательно имеет тот же тип, что и исходный. Допустим, у нас есть список заказов, и в каждом заказе есть список продуктов.

record Order(String customer, List<Product> products) {
}

record Product(String brand, String modelName, BigDecimal price) {
}
Что бы вы сделали, если бы требовалось узнать, сколько денег поступает из списка заказов? Для каждого заказа вам нужно будет получить список присутствующих в нем продуктов, а для каждого продукта в этих списках нужно получить его стоимость. После этого вам требуется суммировать все эти цены, и так вы получите результат. При переводе приведенного выше на Map / Reduce вам необходимо:
  1. Сопоставить каждый заказ со списком продуктов.
  2. Отобразить для каждого продукта его цену.
  3. Суммировать все цены, сложив их друг с другом.
Итак, сделаем это на Java:

public class OrderMapReducer {
    public BigDecimal getTotal(List<Order> orders) {
        return orders.stream() // 1
                     .map(Order::products) // 2
                     .flatMap(List::stream) // 3
                     .map(Product::price) // 4
                     .reduce(BigDecimal::add) // 5
                     .orElse(BigDecimal.ZERO); // 6
    }
}
  1. Создаем поток заказов.
  2. Сопоставляем каждый заказ с его списком продуктов.
  3. Сопоставляем каждый список продуктов с потоком. Обратите внимание, что здесь нам пришлось использовать flatMap, иначе мы получим Stream <Stream <Product>>.
  4. Отображаем для каждого продукта его цену.
  5. Суммируем все цены.
  6. Если список заказов (Order List) пуст, возвращаем zero.
Вот и все! Теперь мы можем создать тест, чтобы убедиться, что все работает должным образом.

@Test
void getTotalPrice() {
    List<Order> orders = createOrders();
    OrderMapReducer orderMapReducer = new OrderMapReducer();
    assertEquals(new BigDecimal(17800), orderMapReducer.getTotal(orders));
}

private static List<Order> createOrders() {
    var strato = new Product("Fender", "Stratocaster", new BigDecimal(3500));
    var sg = new Product("Gibson", "SG", new BigDecimal(4800));
    var lesPaul = new Product("Gibson", "Les Paul", new BigDecimal(4500));
    var rr = new Product("Jackson", "RR", new BigDecimal(5000));

    return List.of(
            new Order("David Gilmour", List.of(strato)),
            new Order("Toni Iommi", List.of(sg)),
            new Order("Randy Rhoads", List.of(lesPaul, rr))
    );
}
Как видите, сопоставление и суммирование (Map and Reduce) помогает в тех случаях, когда вам нужно извлечь информацию из Collection.