Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Correct syntax for Collectors.reducing

I have an Order class and a LineItem class like below:

@AllArgsConstructor
@Getter
@ToString
static class Order {
    long orderId;
    List<LineItem> lineItems;
}

@AllArgsConstructor
@Getter
@ToString
static class LineItem {
    String name;
    BigDecimal price;
}

and a list of orders, from which I want to get a map Map<String,BigDecimal> totalByItem where key is name of LineItem and value total price from all orders in the list. For this I want to use Collectors.groupingBy in combination with Collectors.reducing but struggling with the correct syntax. Can someone help?

List<Order> orders = List.of(new Order(1L, List.of(new LineItem("Item-A", BigDecimal.valueOf(1)),
                                                   new LineItem("Item-B", BigDecimal.valueOf(2)),
                                                   new LineItem("Item-C", BigDecimal.valueOf(3)))),
                             new Order(2L, List.of(new LineItem("Item-A", BigDecimal.valueOf(1)),
                                                   new LineItem("Item-D", BigDecimal.valueOf(4)),
                                                   new LineItem("Item-E", BigDecimal.valueOf(5)))),
                             new Order(3L, List.of(new LineItem("Item-B", BigDecimal.valueOf(2)),
                                                   new LineItem("Item-C", BigDecimal.valueOf(3)),
                                                   new LineItem("Item-D", BigDecimal.valueOf(4)))));

what to put where there are ??? now?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Map<String,BigDecimal> totalByItem =
         orders.stream()
                 .flatMap(order -> order.getLineItems().stream())
                 .collect(Collectors.groupingBy(LineItem::getName,
                          lineItem -> Collectors.reducing(BigDecimal.ZERO,(a,b) -> ???)));

>Solution :

groupingBy takes a Collector as its second argument, so you should not pass the lambda lineItem -> ..., and instead pass the Collector.reducing(...) directly.

Also, since you are reducing a bunch of LineItems to one BigDecimal, you should use the three-parameter overload of reducing, with a mapper

public static <T, U> Collector<T,?,U> reducing(
    U identity,
    Function<? super T,? extends U> mapper,
    BinaryOperator<U> op)

The mapper is where you specify how a LineItem into a BigDecimal. You probably confused this with the second parameter of groupingBy.

So to summarise:

Map<String,BigDecimal> totalByItem =
    orders.stream()
        .flatMap(order -> order.getLineItems().stream())
        .collect(
            Collectors.groupingBy(
                LineItem::getName,
                Collectors.reducing(
                    BigDecimal.ZERO,
                    LineItem::getPrice, // <----
                    BigDecimal::add
                )
            )
        );
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading