java - 选择更有利可图的流结果

标签 java java-8 stream java-stream

目前,我在小型产品管理应用程序中遇到折扣计算问题。

public class Customer {
  private String name;
  private String surname;
  private LocalDate birthDate;
  private String email;
}

public class Order {
  private Customer customer;
  private Product product;
  private Integer quantity;
  private LocalDate estimatedRealizationDate;
}

public class Product {
  private String name;
  private BigDecimal price;
  private Category category;
}

使用 lombok 实用程序。

我有一个包含订单列表的 Orders 类。

public class Orders {

    private final List<Order> productList;

    private static final int MAXIMAL_AGE_WITH_DISCOUNT = 25;
    private static final BigDecimal DISCOUNT_RATIO_FOR_CUSTOMER_YOUNGER_THAN_25 = BigDecimal.valueOf(0.97);
    private static final BigDecimal DISCOUNT_RATIO_FOR_ESTIMATED_DELIVERY_DATE_SMALLER_THAN_2 = BigDecimal.valueOf(0.98);
    private static final int MAXIMAL_DATES_NUMBER_FOR_DISCOUNT = 2;
}

以下一个订单示例:

Orders orderList =
        new Orders(
            newArrayList(
                Order.builder()
                    .product(new Product("LEVER", BigDecimal.valueOf(120), Category.C))
                    .customer(new Customer("JACK", "MULLER", LocalDate.of(1980, 7, 3), "jackmuller@gmail.com"))
                    .estimatedRealizationDate(LocalDate.now().plusDays(2))
                    .quantity(5)
                    .build());

我想为每位 25 岁以下的客户提供 3% 的折扣,并为预计交货日期距此时起不到 2 天的订单提供 2% 的折扣,但我想选择更有利可图的折扣客户。

我编写了我的代码片段,但据我所知,我的版本在某些情况下会结合折扣,这是不可取的。

BigDecimal totalPriceOfAllOrdersAfterPriceReduction() {
        return productList.stream().map(i -> {
            if (between(i.getCustomer().getBirthDate(), LocalDate.now()).getYears() < MAXIMAL_AGE_WITH_DISCOUNT) {
                return i.getProduct().getPrice().multiply(DISCOUNT_RATIO_FOR_CUSTOMER_YOUNGER_THAN_25).multiply(BigDecimal.valueOf(i.getQuantity()));
            }
            if (between(i.getEstimatedRealizationDate(), LocalDate.now()).getDays() < MAXIMAL_DATES_NUMBER_FOR_DISCOUNT) {
                return i.getProduct().getPrice().multiply(DISCOUNT_RATIO_FOR_ESTIMATED_DELIVERY_DATE_SMALLER_THAN_2).multiply(BigDecimal.valueOf(i.getQuantity()));
            }
            return i.getProduct().getPrice();
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

整个操作结束后,我想将所有订单的总价格相加(数量*价格)。

我想通过 Java 流的使用来实现这一点。

预先感谢您的帮助。

最佳答案

只需将第二个 if 放在第一个 if 的 else 部分

BigDecimal totalPriceOfAllOrdersAfterPriceReduction() {
        return productList.stream().map(i -> {
            if (between(i.getCustomer().getBirthDate(), LocalDate.now()).getYears() < MAXIMAL_AGE_WITH_DISCOUNT) {
                return i.getProduct().getPrice().multiply(DISCOUNT_RATIO_FOR_CUSTOMER_YOUNGER_THAN_25).multiply(BigDecimal.valueOf(i.getQuantity()));
            } else{
               if (between(i.getEstimatedRealizationDate(), LocalDate.now()).getDays() < MAXIMAL_DATES_NUMBER_FOR_DISCOUNT) {
                   return i.getProduct().getPrice().multiply(DISCOUNT_RATIO_FOR_ESTIMATED_DELIVERY_DATE_SMALLER_THAN_2).multiply(BigDecimal.valueOf(i.getQuantity()));
               }
            }
            return i.getProduct().getPrice();
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

另一个使其更具可读性和可跟踪性的方法是在订单上添加“折扣”字段,然后

 @Builder
    @Getter
    @ToString
    public static class Order {
        private Customer customer;
        private Product product;
        private Integer quantity;
        private LocalDate estimatedRealizationDate;
        private BigDecimal discount = BigDecimal.ZERO;

        public boolean threePercent(){
            return Period.between(this.getCustomer().birthDate, LocalDate.now()).getYears() < MAXIMAL_AGE_WITH_DISCOUNT;
        }

        public boolean twoPercent(){
            return Period.between(this.estimatedRealizationDate, LocalDate.now()).getYears() < MAXIMAL_DATES_NUMBER_FOR_DISCOUNT;
        }


    }

    public static Order update(Order o){
        if(o.threePercent()){
            o.discount = DISCOUNT_RATIO_FOR_CUSTOMER_YOUNGER_THAN_25;
        }else{
            if(o.twoPercent()){
                o.discount = DISCOUNT_RATIO_FOR_ESTIMATED_DELIVERY_DATE_SMALLER_THAN_2;
            }
        }
        return o;
    }

    public static BigDecimal totalPriceOfAllOrdersAfterPriceReduction(List<Order> orders){
        return orders
                .stream()
                .map(Scratch::update)
                .peek(System.out::println)
                .map(o -> o.product.price.multiply(o.discount).multiply(BigDecimal.valueOf(o.quantity)))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

关于java - 选择更有利可图的流结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55220568/

相关文章:

java - SwingWorker要更新TreeModel吗?

java - Play Framework 1.2.6 连接多个数据库

java - Android中SdCard路径的正确路径?

Java 8 - 使用许多过滤器的过滤器集合

time - 如何使用java 8 time API获取下一个MonthDay(下一个圣诞节)?

Java 8 Comparator nullsFirst naturalOrder 混淆

flash - 使用 Flash 或 Silverlight 进行语音识别

java - 在传递给 Java 8 Streams 的映射函数中实现检查异常处理的更好方法是什么

java - SubscribeOn 仅使用池中的 1 个线程

c++ - 在 C++ 应用程序中使用 C 库的标准输出