【问题标题】:Find the earliest date among 3 dates查找 3 个日期中最早的日期
【发布时间】:2013-04-04 20:20:07
【问题描述】:

我在 Java 中有三个日期:a、b、c。这些日期中的任何一个或所有日期都可能为空。在没有大量 if-else 块的情况下,确定 a、b、c 中最早日期的最有效方法是什么?

【问题讨论】:

  • 你试过什么效率不高?
  • 您需要知道哪个日期最早(即将它与变量绑定),还是只知道值?
  • 您可以将每个 Date 转换为其毫秒表示,并使用复合 Math.min 来确定最小值
  • null 是否大于或小于任何日期?
  • 我想要 a、b、c 中最早的实际日期。任何日期都比空日期好。

标签: java date


【解决方案1】:

没有绕过空检查,但通过一些重构你可以让它变得轻松。

创建一个安全地比较两个日期的方法:

/**
 * Safely compare two dates, null being considered "greater" than a Date
 * @return the earliest of the two
 */
public static Date least(Date a, Date b) {
    return a == null ? b : (b == null ? a : (a.before(b) ? a : b));
}

然后结合对它的调用:

Date earliest = least(least(a, b), c);

实际上,您可以将此作为任何Comparable 的通用方法:

public static <T extends Comparable<T>> T least(T a, T b) {
    return a == null ? b : (b == null ? a : (a.compareTo(b) < 0 ? a : b));
}

【讨论】:

    【解决方案2】:

    Java 8+ oneliner。为了安全起见,添加了空检查。传递任意数量的日期。

    public static Date min(Date... dates) {
        return Arrays.stream(dates).filter(Objects::nonNull).min(Date::compareTo).orElse(null);
    }
    

    不安全,但要短得多:

    public static Date min(Date... dates) {
        return Collections.min(Arrays.asList(dates));
    }
    

    Not null safe没有新方法:

    Collections.min(Arrays.asList(date1, date2));
    

    【讨论】:

    • 如果您使用 Java 或更高版本,则不应使用 Date。该课程设计不良且早已过时。根据具体要求使用Instantjava.time, the modern Java date and time API 中的另一个类。即使在 Java 6 或 7 上,您也可以考虑使用 ThreeTen Backport
    • * 使用 Java 8 或更高版本
    • @OleV.V.在大多数情况下,我更喜欢使用Date,因为在带有 Spring MVC (spring.jackson.serialization.write-dates-as-timestamps=true) 的 DTO 中使用它没有问题,JavaScript(Angular、React 等)和使用 REST 的 Java 之间没有时区问题。在 JS 中只需使用 new Date(timeFromServer) 而不使用任何解析器。当Date 来自前端并与 Hibernate(也是Date)一起进入数据库时​​,您永远不会考虑时区,反之亦然。它也与 Swagger (OpenAPI) 完美配合。所有新旧框架都很好地支持它。新的时间 API 非常适合时间数学。
    • Date 多年来造成了无数时区错误。 Hibernate 5 支持 java.time 就好了。 jackson-modules-java8 也是。口味不同。
    【解决方案3】:

    嗯,“效率”有一些不同的含义,但我认为比较三个日期不会有效率问题。事实上,它真的很便宜。你可以试试这个方法:

    SortedSet<Date> dates = new TreeSet<Date>();
    dates.add(date1);
    dates.add(date2);
    // ...
    dates.add(dateN);
    Date earliest = dates.first();
    

    或者,也许更优雅:

    for (Date date : someDates) {
       if (date != null) {
          dates.add(date);
       }
    }
    Date earliest = dates.first();
    

    【讨论】:

      【解决方案4】:

      一些使用流的 Java 8 方法。第一个将在比较之前过滤空值,第二个将它们放在列表的末尾。

      Date minDate = Arrays.asList(date1, date2, etc).stream()
           .filter(Objects::nonNull).min(Date::compareTo).get()
      

      Date minDate = Arrays.asList(date1, date2, etc).stream()
          .sorted((a, b) -> {
              //some kind of custom sort.
              if(a == null && b == null) return 0;
              if(a == null) return 1;
              if(b == null) return -1;
              return a.compareTo(b);
          }).findFirst().get()
      

      【讨论】:

        【解决方案5】:

        当 Apache Commons 可用时,您可以使用 ObjectUtils.min

        Date earliest = ObjectUtils.min(a, b, c);
        

        【讨论】:

          【解决方案6】:

          与此同时,您可能正在使用 Java 8 LocalDate(而不是旧的 java.util.Date)

          对于 Java 8 LocalDate,使用此方法获取日期列表中最早的日期:

          import java.time.LocalDate;
          
          public static LocalDate earliestDate(LocalDate... dates) {
              return
                  Arrays
                  .stream(dates)
                  .filter(Objects::nonNull)
                  .min(LocalDate::compareTo)
                  .orElse(null);
          }
          

          【讨论】:

          • 我的回答专门涵盖了 Java 8 LocalDate,其他人都没有。
          • 我没有注意到。很好,我将我的反对票改为赞成票,并删除了我的评论。我建议您添加一些散文来解释您对LocalDate 的使用、好处以及您的答案如何不同和更好。
          【解决方案7】:

          使用java Date对象http://docs.oracle.com/javase/6/docs/api/java/util/Date.html

          然后你可以使用这些对象的 before() 和 after() 函数

          【讨论】:

            【解决方案8】:

            前后使用:

              /**
                 * find Min Dates
                 * @param date1
                 * @param date2
                 * @return
                 */
                public static Date minDate(Date date1, Date date2) {
                    // if date1 before date2 then return date1 else return date2
                    return date1.before(date2) ? date1 : date2;
                }
                 /**
                 * find Max Dates
                 * @param date1
                 * @param date2
                 * @return
                 */
                public static Date maxDate(Date date1, Date date2) {
                    // if date1 after date2 then return date1 else return date2
                    return date1.after(date2) ? date1 : date2;
                }
            

            【讨论】:

              【解决方案9】:

              使用流:

              Date min = Stream.of(date1, date2, etc)
                .filter(Objects::nonNull)
                .min(Date::compareTo)
                .orElse(null);
              

              如果您的数组不包含 NULL 值,您可以使用 Ordering

              Ordering.natural().min(date1, date2, etc);
              

              【讨论】:

                【解决方案10】:

                另一种方式是使用java.util.Collections.min(collection):

                返回: 根据元素的自然顺序,给定集合的最小元素。

                public static Date getEarliestDate(List<Date> dates) {
                
                    if (dates == null || dates.isEmpty())
                        return null;
                
                    dates.removeIf(Objects::isNull);
                
                    return dates.isEmpty() ? null : Collections.min(dates);
                }
                

                【讨论】:

                  【解决方案11】:

                  你可以使用

                  date1.compareTo(anotherDate)
                  

                  返回:

                  如果参数 Date 等于此 Date,则值为 0;如果此 Date 在 Date 参数之前,则值小于 0;如果此 Date 在 Date 参数之后,则值大于 0。

                  投掷:

                  NullPointerException - 
                  

                  如果 anotherDate 为空。

                  【讨论】:

                    【解决方案12】:

                    只是另一个版本的想法和乐趣

                    new Date(Math.min(a != null ? a.getTime() : Long.MAX_VALUE
                    , Math.min(b != null ? b.getTime() : Long.MAX_VALUE
                    , c != null ? c.getTime() : Long.MAX_VALUE)))
                    

                    【讨论】:

                      【解决方案13】:
                      List.of(date1, date2)
                                      .stream()
                                      .min(Date::compareTo)
                                      .get();
                      

                      【讨论】:

                      • NullPointerException,至少阅读问题 - 顺便说一句,问题是 8 岁,已经有答案,已经有一个可接受的答案,并且之前的答案(超过 3 个)已经显示相同概念但更好(更完整,一些解释,没有NullPointerException
                      • 对不起我的错,真的没有看问题。但是,这是一个简单的解决方案,当您确定所有日期都不为空时,我想分享它可以在私有方法中使用
                      猜你喜欢
                      • 2012-08-18
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-06-09
                      • 2021-10-29
                      • 1970-01-01
                      • 2021-12-23
                      • 1970-01-01
                      • 2016-04-30
                      相关资源
                      最近更新 更多