Java 选择更有利可图的流结果

Java 选择更有利可图的流结果,java,java-8,stream,java-stream,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 I

目前,我正在努力解决我的小型产品管理应用程序中的折扣计算问题

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;
}
与龙目岛公用事业公司

我有一个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;
}
我想给每个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);
    }
BigDecimalTotalPriceOfAllordersAfterPriceReduction(){
返回productList.stream().map(i->{
如果(介于(i.getCustomer().getBirthDate()、LocalDate.now()).getYears()<带折扣的最大年龄){
返回i.getProduct().getPrice().multiply(小于25岁的客户的折扣率)。multiply(BigDecimal.valueOf(i.getQuantity());
}
如果(介于(i.getEstimatedRealizationDate()、LocalDate.now()).getDays()<折扣的最大日期数){
返回i.getProduct().getPrice().multiply(折扣率,用于估计的交货日期小于2)。multiply(BigDecimal.valueOf(i.getQuantity());
}
返回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);
    }
BigDecimalTotalPriceOfAllordersAfterPriceReduction(){
返回productList.stream().map(i->{
如果(介于(i.getCustomer().getBirthDate()、LocalDate.now()).getYears()<带折扣的最大年龄){
返回i.getProduct().getPrice().multiply(小于25岁的客户的折扣率)。multiply(BigDecimal.valueOf(i.getQuantity());
}否则{
如果(介于(i.getEstimatedRealizationDate()、LocalDate.now()).getDays()<折扣的最大日期数){
返回i.getProduct().getPrice().multiply(折扣率,用于估计的交货日期小于2)。multiply(BigDecimal.valueOf(i.getQuantity());
}
}
返回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);
    }
@Builder
@吸气剂
@托斯特林
公共静态类秩序{
私人客户;
私人产品;
私有整数数量;
私有LocalDate estimatedRealizationDate;
私有BigDecimal折扣=BigDecimal.0;
公共布尔值百分之三(){
返回期.between(this.getCustomer().birthDate,LocalDate.now()).getYears()<最大年龄折扣;
}
公共布尔值百分之二(){
返回期.between(this.estimatedRealizationDate,LocalDate.now()).getYears()o.product.price.multiply(o.discount).multiply(BigDecimal.valueOf(o.quantity)))
.reduce(BigDecimal.ZERO,BigDecimal::add);
}

附带问题:为什么要使用
BigDecimal
?最小货币的
int
就足够了吗?类似于
intpriceincents=100
其中
100
cents等于
1
dollar?在处理货币时,使用BigDecimal类是常见的,并且被认为是安全的,因此我在本例中使用它。顺便说一句,您的解决方案相当可观,在问题解决后,我肯定会深入研究。我想是精度的损失导致了
int
“不安全”,您当然可以使用
双倍的
值进行计算,但然后再次返回
int
。这样,您可以在整个计算过程中保持精度,然后再次使用
int
s
 @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);
    }