有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用流根据第二个列表中的值更新一个列表中的对象

我有两个相应的列表:

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

目标是对折扣进行求和,这意味着将actualPromotions中的discountRate添加到booksToReturn列表中的discountRate值。两个列表中的对象可以通过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()));
            }
        );

我只是在探索溪流,我认为我的解决方案很笨拙。您将如何使用流和函数方法以更优雅的方式解决这个问题


共 (3) 个答案

  1. # 1 楼答案

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

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

    然后我会:

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

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

    booksToReturn.forEach(e -> 
           Optional.ofNullable(accumulator.get(e.getIdOfBook()))
              .ifPresent(p -> e.setDiscountRate(e.getDiscountRate() + p.getDiscountRate()))
    );
    

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

  2. # 2 楼答案

    一种方法是使用:

    booksToReturn.forEach(p -> actualPromotions.stream()
                    .filter(actualPromotion -> actualPromotion.getIdOfBook().equals(p.getIdOfBook()))
                    .forEach(actualPromotion -> p.setDiscountRate(p.getDiscountRate() + actualPromotion.getDiscountRate())));
    

    假设actualPromotion.getIdOfBook()p.getIdOfBook()Set中是唯一的

  3. # 3 楼答案

    我没有对此进行测试: 试试这个

      Map<Long,Integer> map1 = actualPromotions
       .stream() 
       .collect(Collectors.toMap(TimeDiscount::getIdOfBook,TimeDiscount::getDiscountRate));
    

    然后将此地图用于:

    booksToReturn.stream()
       .filter(b->map1.containsKey(b.getIdOfBook()))
       .map(p->{p.setDiscountRate(map1.get(p.getIdOfBook()) + p.getDiscountRate());return p;}) // .map(p->setSumDiscountRate(map1.get(p.getIdOfBook()) + p.getDiscountRate()))
       .collect(Collectors.toList());
    

    尝试在BookOverallData类中声明一个新方法

    public BookOverallData setSumDiscountRate(Integer dis){
      this.discountRate = dis;
      return this;
    }