I have two corresponding lists:
public class BookOverallData {
    private Long idOfBook;
    private String title;
    private String authour;
    private BigDecimal basePrice;
    private Integer discountRate;
}
public class TimeDiscount {    
    private Long idOfBook;
    private Integer discountRate;    
}
Set<BookOverallData> booksToReturn
Set<TimeDiscount> actualPromotions
The goal is to sum discounts, which means adding discountRate from actualPromotions to discountRate value from the booksToReturn list. The objects from both lists can be matched by idOfBook.
This is how I solved it
booksToReturn.forEach(
            p -> {
                final Optional<TimeDiscount> promotion = actualPromotions.stream().filter(ap -> Objects.equals(ap.getIdOfBook(), p.getIdOfBook())).findFirst();
                promotion.ifPresent(ap -> p.setDiscountRate(ap.getDiscountRate() + p.getDiscountRate()));
            }
        );
I'm just exploring streams and I think my solution is clumpy. How would you solve this problem in more elegant fashion, with usage of streams and functional approach?
I'd first create a mapping from TimeDiscount::getIdOfBook to TimeDiscount:
Map<Long, TimeDiscount> accumulator = 
      actualPromotions.stream()
                     .collect(toMap(TimeDiscount::getIdOfBook, Function.identity()));
Then I'd do:
booksToReturn.forEach(e -> {
       TimeDiscount timeDiscount = accumulator.get(e.getIdOfBook());
       if (timeDiscount != null) e.setDiscountRate(e.getDiscountRate() + timeDiscount.getDiscountRate());
});
or if you want to stay with the use of Optional for some reason.
booksToReturn.forEach(e -> 
       Optional.ofNullable(accumulator.get(e.getIdOfBook()))
          .ifPresent(p -> e.setDiscountRate(e.getDiscountRate() + p.getDiscountRate()))
);
This improves upon the inefficient lookup in actualPromotions.stream() for each element of booksToReturn. 
One way you can do it is using:
booksToReturn.forEach(p -> actualPromotions.stream()
                .filter(actualPromotion -> actualPromotion.getIdOfBook().equals(p.getIdOfBook()))
                .forEach(actualPromotion -> p.setDiscountRate(p.getDiscountRate() + actualPromotion.getDiscountRate())));
Assuming actualPromotion.getIdOfBook() and p.getIdOfBook() would be unique across your Sets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With