【问题标题】:A date sorting algorithm日期排序算法
【发布时间】:2014-12-17 21:34:04
【问题描述】:

注意,这个比较器有效。我只是想知道是否有更优雅的方式来做到这一点? 基本上,我有一个 mm/dd/yyyy(或 MM/dd/yyyy)形式的日期 LinkeList。由于显而易见的原因,进行常规字符串排序将无法正常工作,因为 2015 年 1 月 1 日将在 1997 年 12 月 12 日之前出现。所以我写了这个比较器。

不过,有一个问题。有时日期可能为空(或空白),因此它应该先升序,或最后降序。

我编写了这个比较器,并将其发送到 Collections.sort()。请记住,它确实有效,但必须有更简单的方法?

哦,我忘记提的一件事是这个声明:

public class DateFormats { 
    ...
    public static final SimpleDateFormat PTL_MMddyyyy = new SimpleDateFormat("MM/dd/yyyy");
    ...
}

比较器如下:

public static class dateSort implements Comparator<String> {
    @Override
    public int compare(String cur, String nxt) {
        String veryEarlyDate = "01/01/0001";
        Date curdate = null;
        Date nxtdate = null;
        cur = ((cur != null && !cur.trim().isEmpty()) ? cur : veryEarlyDate);
        nxt = ((nxt != null && !nxt.trim().isEmpty()) ? nxt : veryEarlyDate);
        try {
            curdate = DateFormats.PTL_MMddyy.parse(cur);
            nxtdate = DateFormats.PTL_MMddyy.parse(nxt);
        } catch (Exception e) {
            System.out.println("Bad date " + cur + " or " + nxt);
            assert (false) : e.getMessage();
        }
        return curdate.compareTo(nxtdate);
    }
}

【问题讨论】:

  • 为什么不对Date 对象列表进行排序,而不是尝试操作字符串列表?
  • 您是否必须拥有一组字符串而不是一组基于日期的对象(例如LocalDate)?一般来说,最好尽可能多地保持数据的“自然”形式。
  • html页面上是这样的,MM/dd/yyyy
  • HTML 页面中有很多整数、长整数和其他数字元素,它们首先被读取为Strings,这并不意味着我不能将它们存储为它们的真实类型。

标签: java sorting date comparator


【解决方案1】:

您应该在 DateFormat 类中实现可比较。然后,实现 compareTo 方法并比较对象。如果较大则返回 1,如果相等则返回 0,如果较小则返回 -1。

public class DateFormat implements Comparable{

... 

   public int compareTo(Object o){
       DateFormat df = (DateFormat)o; 
       int result; 
       ... //do desired comparison 
       //and set result to -1, 0 or 1 depending on result.
       return result; 
   }
}

然后你可以使用 Arrays.sort(DateFormat[] dateFormatArray);对 DateFormat 对象的集合进行排序。

【讨论】:

  • 但是我必须为每种日期格式编写一个单独的比较器?
  • compareTo 方法的目的是解决所有情况。您应该考虑 DateFormat 的所有情况并进行比较,并考虑如何比较它们。实现比较并在线查找更多 compareTo 示例,以更好地了解如何实现 Comparable 接口。
【解决方案2】:

不确定我是否得到了你想要的,但我能想到的一种简单方法是将日期转换为整数,然后进行比较。

MM/dd/yyyy -> yyyyMMdd (yyyy * 10000 + MM * 100 + dd)
1/1/2015   -> 20150101
12/12/1997 -> 19971212

【讨论】:

  • 空白和空值只是0?这可以工作,但我仍然必须操纵。做一个 split("/") 然后 Integer.parseInt(fields[2])*10000 + Integer.parseInt(fields[1])*100 + Integer.parseInt(fields[1]);
【解决方案3】:

Java 的 Data 和 Jodatime 的 LocalDate 已经是 Comparable,因此不需要额外的代码。

【讨论】:

    【解决方案4】:

    如果您的 LinkedList 使用 Object[] 而不是 String,我认为会更优雅(简单 + 合乎逻辑)。 当您将字符串添加到linkedList 时,在那时对其进行解析。我会避免在比较器中解析它。

    if(string != null)
        Object[] toAddToList = new Object[]{string, PTL_MMddyyyy.parse(string)};
    else
        Object[] toAddToList = new Object[]{null, null};
    

    然后

        public static class dateSort implements Comparator<Object[]> 
        {
            public int compare(Object[] cur, Object[] nxt) 
            {
               //TODO: add null check
               return ((Date)cur[1]).compareTo((Date)nxt[1]);
            }
        }
    

    【讨论】:

      【解决方案5】:

      使用日期时间对象

      一些有经验的人建议更好的策略是使用自然数据类型而不是字符串。数字值应该是数字对象,UUID 值应该是 UUID 对象,日期时间值应该是日期时间对象。

      您的业务逻辑应该使用这些对象。渲染到字符串应该只发生在:

      乔达时间

      正如一些人所建议的,Joda-Time 是要走的路,而不是与 Java 捆绑在一起的臭名昭著的麻烦 java.util.Date/.Calendar 类。或者,您可以使用 Java 8 中内置的 java.time(受 Joda-Time 启发)。

      Comparable

      Joda-Time 实现了Comparable。所以,准备好进行排序了。

      示例代码

      这里是一些示例 Joda-Time 2.6 代码。

      // Simulate input.
      List<String> listInput = new ArrayList<>();
      DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy" );
      listInput.add( formatter.print( LocalDate.now() ) );
      listInput.add( formatter.print( LocalDate.now().plusDays( 5 ) ) );
      listInput.add( formatter.print( LocalDate.now().minusDays( 13 ) ) );
      

      将字符串转换为LocalDate 对象。此类表示仅日期值,没有时间和时区。

      // Convert strings to LocalDate objects.
      List<LocalDate> listLocalDate = new ArrayList<>();
      for ( String s : listInput ) {
          try {
              LocalDate x = formatter.parseLocalDate( s );
              listLocalDate.add( x );
          } catch ( IllegalArgumentException e ) {
              // …
              // Handle invalid data input.
          }
      }
      Collections.sort( listLocalDate );
      

      转储到控制台。

      System.out.println( "listInput : " + listInput );
      System.out.println( "listLocalDate : " + listLocalDate );
      

      运行时。

      listInput : [12/17/2014, 12/22/2014, 12/04/2014]
      listLocalDate : [2014-12-04, 2014-12-17, 2014-12-22]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        • 1970-01-01
        • 2011-02-19
        相关资源
        最近更新 更多