在下面的代码中,我试图计算一个篮子的总价格,其中篮子是一个HashMap,其中包含产品作为键,数量作为值。促销活动可作为晋升名单提供。
我正在循环每一个地图条目,并为他们中的每一个迭代促销。如果促销匹配,我将使用促销价格(promotion.computeDiscountedPrice())并将促销从列表中删除(因为促销只适用于产品&产品在列表中是唯一的)
如果没有晋升,我们就执行块。
如果(!offerApplied) { /* .*/ }
请您帮助我使用Java8StreamAPI执行同样的操作吗?
BigDecimal basketPrice = new BigDecimal("0.0");
Map<String, Integer> basket = buildBasket(input);
List<Promotion> promotions = getOffersApplicable(basket);
for (Map.Entry<String, Integer> entry : trolley.entrySet()) {
boolean offerApplied = false;
Iterator<Promotion> promotionIterator = promotions.iterator();
while (promotionIterator.hasNext()) {
Promotion promotion = promotionIterator.next();
if (entry.getKey().equalsIgnoreCase(offer.getProduct().getProductName())) {
basketPrice = basketPrice.add(promotion.computeDiscountedPrice());
offerApplied = true;
promotionIterator.remove();
break;
}
if (!offerApplied) {
basketPrice = basketPrice.add(Product.valueOf(entry.getKey()).getPrice()
.multiply(new BigDecimal(entry.getValue())));
}
}
return basketPrice;发布于 2018-03-14 05:26:54
最简单、更简洁的解决方案比迭代整个促销列表具有更好的性能,首先创建由产品id标识的促销映射(小写或大写,假设使用equalsIgnoreCase(..)不会发生大小写冲突)。
Map<String, Promotion> promotionByProduct = promotions.stream()
.collect(Collectors.toMap(prom -> prom.getProduct()
.getProductName().toLowerCase(), Function.identity()));这将避免在搜索促销时遍历整个数组,也避免了从其中删除项目,如果是ArrayList,则每次使用删除时都需要将其余的元素转移到左边。
BigDecimal basketPrice = basket.keySet().stream()
.map(name -> Optional.ofNullable(promotionByProduct.get(name.toLowerCase()))
.map(Promotion::computeDiscountedPrice) // promotion exists
.orElseGet(() -> Product.valueOf(name).getPrice()) // no promotion
.multiply(BigDecimal.valueOf(basket.get(name))))
.reduce(BigDecimal.ZERO, BigDecimal::add);它对篮子中的每个产品名称进行迭代,然后检查是否存在促销,它使用computeDiscountedPrice方法,否则它将使用Product.valueOf(..)查找产品并获得价格,然后它将该值与篮子中的产品数量相乘,最后用BigDecimal.add()方法减少结果(添加篮子的所有值)。
需要注意的是,在您的代码中,您不会将quantity的结果乘以promotion.computeDiscountedPrice()的结果(上面的代码确实如此),我不确定这是代码中的类型,还是它的行为方式。
如果实际情况是它的行为方式(您不希望将quantity乘以promotion.computeDiscountedPrice()),则代码如下:
BigDecimal basketPrice = basket.keySet().stream()
.map(name -> Optional.ofNullable(promotionByProduct.get(name.toLowerCase()))
.map(Promotion::computeDiscountedPrice)
.orElseGet(() -> Product.valueOf(name).getPrice()
.multiply(BigDecimal.valueOf(basket.get(name)))))
.reduce(BigDecimal.ZERO, BigDecimal::add);这里唯一的值乘以quantity将是用Product.valueOf(name).getPrice()获得的产品价格。
最后,另一个选项,全部在一行中,不使用地图(迭代促销)使用第一种方法(最后按数量进行倍数):
BigDecimal basketPrice = basket.keySet().stream()
.map(name -> promotions.stream()
.filter(prom -> name.equalsIgnoreCase(prom.getProduct().getProductName()))
.findFirst().map(Promotion::computeDiscountedPrice) // promotion exists
.orElseGet(() -> Product.valueOf(name).getPrice()) // no promotion
.multiply(BigDecimal.valueOf(basket.get(name))))
.reduce(BigDecimal.ZERO, BigDecimal::add);https://stackoverflow.com/questions/49267766
复制相似问题