I have a class:

public class ProductInvoice {
     //Some other properties.
    private List<ProductEntry> productEntries = newArrayList();


public class ProductEntry {
//other properties
    private Long quantity;
    private Long productId;

Now I need to prepare a map of productId vs quantity by iterating over a collection of ProductInvoice objects:

List<ProductInvoice> entries = productInvoiceRepository.findByProductEntries_ProductIdIn(productIds);
        Map<Long, Long> productIdVsQuantity = newHashMap();
        entries.forEach( pi -> pi.getProductEntries().forEach(pe -> {
            if (productIdVsQuantity.containsKey(pe.getProductId())) {
                productIdVsQuantity.put(pe.getProductId(), productIdVsQuantity.get(pe.getProductId()) + pe.getQuantity());
            } else {
                productIdVsQuantity.put(pe.getProductId(), pe.getQuantity());

Could there be a better way of doing this? I think this can be optimized using better lambda usage.


1 Answer 1


First, you can use Stream.flatMap() to convert a Stream of ProductInvoice to ProductEntries.

Next, you just need suitable Collector implementations to sum all the quantities per product ID, and group by that...

Putting it all together:

Map<Long, Long> result = productInvoiceRepository
                            .stream().flatMap(v -> v.getProductEntries().stream())

BTW, you may want to consider a better method name for findByProductEntries_ProductIdIn() to remove the underscore...

  • 1
    \$\begingroup\$ findByProductEntries_ProductIdIn() name actually just to add clarity for spring repository. the underscore (which is optional) adds clarity about product Id is present in child class. \$\endgroup\$
    – MohdAdnan
    Commented Sep 29, 2015 at 10:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.