【问题标题】:Improving code with Java 8 Predicates - comparing multiple arguments使用 Java 8 谓词改进代码 - 比较多个参数
【发布时间】:2020-04-30 16:06:56
【问题描述】:

我不确定我的标题是否正确。我想对请求执行一些验证。我在现有代码的很多地方都有这个条件测试。它位于实用程序类中。方法是DoesRequestLineFallsWithinDateRange(object)。

我想知道我是否可以通过使用 Predicates 并停用该方法来改进代码并使用 Java 8 更加优雅。

处理请求: 我想检查每一行是否满足条件。所以调用方法调用这个实用程序类来检查每一行是否在数据范围内。在本例中,是订阅期内的项目(requestLine)。

一个请求进来,一些处理将订阅成员对象添加到请求行。 然后在每一行上调用实用方法来检查请求行是否在订阅期内。

该方法首先检查它应该使用的日期字段是否为空,以防止出现空异常。

然后使用请求行日期,与订阅成员的开始/结束日期字段进行比较以确定日期是否在范围内。

我想用 Java 8 Predicate 函数调用替换该方法。

这里是测试集合中每一行是否在数据范围内的方法示例。

public static boolean DoesRequestLineFallsWithinDateRange(RequestLine requestLine) {
    if (isDatesNotNull(requestLine)) {
      return requestLine.getServiceStartDate().compareTo(requestLine.getSubscription().getStartDate()) >= 0
          && requestLine.getServiceStartDate().compareTo(requestLine.getSubscription().getEndDate()) <= 0;
    }
   return false;
  }

public class RequestLine(){
   private Date serviceStartDate;
   private Subscription subscription;
.....

}

【问题讨论】:

  • 您应该将该方法设为RequestLine 类的非静态无参数方法,即使其不仅仅是DTO
  • 你没有展示你是如何处理整个请求的。你有RequestLine 的列表吗?请澄清

标签: java java-8 functional-programming predicate


【解决方案1】:

这是使用 Java 8 PredicatesLocalDate API 编写的示例代码

    public boolean doesRequestLineFallsWithinDateRange(RequestLine requestLine)
    {
        BiPredicate<LocalDate, LocalDate> afterDatePredicate = (startData, endDate) -> (startData.isAfter(endDate));
        BiPredicate<LocalDate, LocalDate> beforeDatePredicate = (startData, endDate) -> (startData.isBefore(endDate));

        if (Objects.isNull(requestLine))
        {
            return false;
        }

        LocalDate serviceStartDate = requestLine.getServiceStartDate();
        LocalDate startDate = requestLine.getSubscription().getStartDate();
        LocalDate endDate = requestLine.getSubscription().getEndDate();

        return afterDatePredicate.test(serviceStartDate, startDate) && beforeDatePredicate.test(serviceStartDate,
                endDate);

    }

引用的 Java 代码

RequestLine.java

public class RequestLine

{
    private Subscription subscription;
    private LocalDate serviceStartDate;

    // getters and setters
}

Subscritpion.java

public class Subscription
{
    private LocalDate startDate;
    private LocalDate endDate;

    // getters and setters
}

【讨论】:

    【解决方案2】:

    我尝试集成您的代码以使用方法引用作为谓词并过滤 RequestLine 流。有趣的方法是execute:它接收一个流并使用对doesRequestLineFallsWithinDateRange 方法的引用对其进行过滤。

    
    import java.util.Date;
    import java.util.stream.Stream;
    
    public class RequestLine {
    
        public void execute(Stream<RequestLine> stream) {
            // this is the interesting code
            stream.filter(this::doesRequestLineFallsWithinDateRange);
        }
    
        public boolean doesRequestLineFallsWithinDateRange(RequestLine requestLine) {
            if (isDatesNotNull(requestLine)) {
                return requestLine.getServiceStartDate().compareTo(requestLine.getSubscription().getStartDate()) >= 0
                        && requestLine.getServiceStartDate().compareTo(requestLine.getSubscription().getEndDate()) <= 0;
            }
            return false;
        }
    
        //code created to complete the example
        public static class Subscription {
    
            private Date startDate;
    
            public Date getEndDate() {
                return endDate;
            }
    
            private Date endDate;
    
            public Date getStartDate() {
                return  startDate;
            }
        }
    
    
    
        private boolean isDatesNotNull(RequestLine requestLine) {
            return requestLine.serviceStartDate!=null;
        }
    
    
        public Date getServiceStartDate() {
            return serviceStartDate;
        }
    
        public Subscription getSubscription() {
            return subscription;
        }
    
        private Date serviceStartDate;
        private Subscription subscription;
    
    }
    

    【讨论】:

      【解决方案3】:

      使用Predicate::and 链接多个谓词

      Predicate<RequestLine> rlPred = this::isDatesNotNull;
      
      rlPred = rlPred.and(p -> p.getServiceStartDate().compareTo(p.getSubscription().getStartDate()) >= 0)
                     .and(p -> p.getServiceStartDate().compareTo(p.getSubscription().getEndDate()) <= 0);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-16
        相关资源
        最近更新 更多