使用流基于来自第二个列表的值更新一个列表中的对象

MyW*_*Way 6 java functional-programming java-8 java-stream

我有两个相应的列表:

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
Run Code Online (Sandbox Code Playgroud)

我们的目标是要总结的折扣,这意味着将discountRate来自actualPromotionsdiscountRate价值从booksToReturn列表中.两个列表中的对象可以匹配idOfBook.

这就是我解决它的方式

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()));
            }
        );
Run Code Online (Sandbox Code Playgroud)

我只是在探索溪流,我认为我的解决方案是块状的.如何使用流和功能方法以更优雅的方式解决这个问题?

Ous*_* D. 3

我首先创建一个从TimeDiscount::getIdOfBook到 的映射TimeDiscount

Map<Long, TimeDiscount> accumulator = 
      actualPromotions.stream()
                     .collect(toMap(TimeDiscount::getIdOfBook, Function.identity()));
Run Code Online (Sandbox Code Playgroud)

然后我会这样做:

booksToReturn.forEach(e -> {
       TimeDiscount timeDiscount = accumulator.get(e.getIdOfBook());
       if (timeDiscount != null) e.setDiscountRate(e.getDiscountRate() + timeDiscount.getDiscountRate());
});
Run Code Online (Sandbox Code Playgroud)

Optional或者如果您出于某种原因想继续使用。

booksToReturn.forEach(e -> 
       Optional.ofNullable(accumulator.get(e.getIdOfBook()))
          .ifPresent(p -> e.setDiscountRate(e.getDiscountRate() + p.getDiscountRate()))
);
Run Code Online (Sandbox Code Playgroud)

actualPromotions.stream()这改进了的每个元素的低效查找booksToReturn