【问题标题】:Sort objects in ArrayList by date?按日期对 ArrayList 中的对象进行排序?
【发布时间】:2011-05-08 11:19:08
【问题描述】:

我找到的每个示例都是按字母顺序执行此操作,而我需要按日期对元素进行排序。

我的 ArrayList 包含其中一个数据成员是 DateTime 对象的对象。在 DateTime 我可以调用函数:

lt() // less-than
lteq() // less-than-or-equal-to

所以为了比较,我可以这样做:

if(myList.get(i).lt(myList.get(j))){
    // ...
}

我应该在 if 块中做什么?

【问题讨论】:

  • 我发布了解决方案,但如果您想深入了解排序,您应该阅读排序算法(冒泡排序、合并排序、快速排序等)。
  • 谢谢,我去看看,我对排序一窍不通
  • 几个有用的 Java 1.8 解决方案可以在这个线程中找到:stackoverflow.com/questions/36361156/…
  • 你可以在这里找到升序和降序的答案stackoverflow.com/a/66772568/5915318

标签: java sorting datetime


【解决方案1】:

您可以使您的对象具有可比性:

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    return getDateTime().compareTo(o.getDateTime());
  }
}

然后你通过调用对它进行排序:

Collections.sort(myList);

但有时您不想更改模型,例如当您想对几个不同的属性进行排序时。在这种情况下,您可以动态创建比较器:

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

但是,仅当您确定比较时 dateTime 不为空时,上述方法才有效。明智的做法是处理 null 以避免 NullPointerExceptions:

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    if (getDateTime() == null || o.getDateTime() == null)
      return 0;
    return getDateTime().compareTo(o.getDateTime());
  }
}

或者在第二个例子中:

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      if (o1.getDateTime() == null || o2.getDateTime() == null)
        return 0;
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

【讨论】:

  • 好答案。为什么需要包含不检查空值的版本?有什么好处?如果正确的方法是第二种,则只能包含它并使重要信息更具吸引力。
  • 两个原因 - 简单和快速失败。您希望代码尽可能简单,并且如果您确定您的属性不应该为 null,您可能希望您的代码在遇到 null 时尽快失败,而不是传递无效数据并从该位置进一步中断引入了无效数据的地方。
  • 如果o1或o2为空,返回0; //这行可能会导致错误,因为返回 0 意味着它们是相等的。
  • @tanyehzheng,这是正确的,它具有误导性,但请注意用于排序的 .compareTo() 和 .equals() 之间存在差异。这实际上取决于您希望在排序期间如何处理空值。
  • 您应该分别检查每个日期的空值并根据需要进行排序(空值排序在序列的开头或结尾)。也就是说,如果一个日期为空且一个日期不为空,则返回 1 或 -1。如果不这样做,空值不会被排序,并且会保留在排序之前它们碰巧在列表中的任何位置。
【解决方案2】:

从 Java 8 开始,List 接口提供了sort 方法。结合lambda 表达式,最简单的解决方案是

// sort DateTime typed list
list.sort((d1,d2) -> d1.compareTo(d2));
// or an object which has an DateTime attribute
list.sort((o1,o2) -> o1.getDateTime().compareTo(o2.getDateTime()));
// or like mentioned by Tunaki
list.sort(Comparator.comparing(o -> o.getDateTime()));

逆向排序

Java 8 还提供了一些方便的反向排序方法。

//requested by lily
list.sort(Comparator.comparing(o -> o.getDateTime()).reversed());

【讨论】:

  • 更好的是list.sort(Comparator.comparing(o -&gt; o.getDateTime()));
  • 这个怎么样:list.sort(Comparator.comparing(MyObject::getDateTime)
  • @Tunaki 怎么做逆向排序?
  • @lily, Collections.sort(list, Collections.reverseOrder());
  • 只是为了确保每个人都在同一页面上,例如:list.sort(Comparator.comparing(MyObject::getDateTime)); 将首先返回最早的日期,最后返回最近的日期。如果您不想要,只需将其反转,如上所示。
【解决方案3】:

您可以使用 Collections.sort 方法。这是一种静态方法。您将列表和比较器传递给它。它对列表使用修改后的归并排序算法。这就是为什么你必须给它传递一个比较器来进行配对比较。

Collections.sort(myList, new Comparator<MyObject> {
   public int compare(MyObject o1, MyObject o2) {
      DateTime a = o1.getDateTime();
      DateTime b = o2.getDateTime();
      if (a.lt(b)) 
        return -1;
      else if (a.lteq(b)) // it's equals
         return 0;
      else
         return 1;
   }
});

请注意,如果 myList 是可比较类型(实现 Comparable 接口的类型)(如 Date、Integer 或 String),您可以省略比较器,将使用自然排序。

【讨论】:

【解决方案4】:
list.sort(Comparator.comparing(o -> o.getDateTime()));

Tunaki 使用 Java 8 lambda 给出的最佳答案恕我直言

【讨论】:

    【解决方案5】:

    鉴于MyObject 具有DateTime 成员和getDateTime() 方法,您可以通过DateTime 对象对包含MyObject 元素的ArrayList 进行排序,如下所示:

    Collections.sort(myList, new Comparator<MyObject>() {
        public int compare(MyObject o1, MyObject o2) {
            return o1.getDateTime().lt(o2.getDateTime()) ? -1 : 1;
        }
    });
    

    【讨论】:

    • 如果我想根据当前系统时间订购怎么办。
    【解决方案6】:

    我就是这样解决的:

    Collections.sort(MyList, (o1, o2) -> o1.getLastModified().compareTo(o2.getLastModified()));
    

    希望对你有帮助。

    【讨论】:

    • 如何按日期反转?
    【解决方案7】:

    未来的观众,我认为这是最简单的解决方案,如果您的模型包含字符串类型的日期(例如“2020-01-01 10:00:00”),那么只需编写以下行来对数据进行排序日期从最新到最旧:

    Collections.sort(messages, (o1, o2) -> o2.getMessageDate().compareTo(o1.getMessageDate()));
    

    【讨论】:

      【解决方案8】:

      我发现这里的所有答案对于一个简单的问题来说都是不必要的复杂(至少对于经验丰富的 Java 开发人员来说,我不是)。我遇到了类似的问题,偶然发现了这个(和其他)解决方案,尽管它们提供了一个指针,但对于我如上所述发现的初学者来说。我的解决方案取决于您的日期在对象中的位置,在这种情况下,日期是 Object[] 的第一个元素,其中 dataVector 是包含您的对象的 ArrayList。

      Collections.sort(dataVector, new Comparator<Object[]>() {
          public int compare(Object[] o1, Object[] o2) {
              return ((Date)o1[0]).compareTo(((Date)o2[0]));
          }
      });
      

      【讨论】:

      • 您的答案比这里的其他答案更简单或更正确?在我看来,例如 WhiteFang32 的答案非常相似且更简洁。
      • 离开了一段时间,所以没有看到回应,但话又说回来,迟到总比没有好。我认为 WhiteFang 的回答简洁是我(当时)缺乏经验的 Java 开发人员眼中的缺点!在我的回复中包含类型转换是关键(至少在我看来)。剩下的就是您声称我的答案比其他人更正确的说法?我想发泄一下......一切都被原谅了!
      • o.getDateTime() 不是关于打字,而是关于 OP 对包含在另一个对象中的 DateTime 对象的描述。如果只有DateDateTime 对象是Comparable,则首先不需要Comparator
      • 并不是说您的答案不太正确或不太好。我只是在寻找信息以帮助我更好地理解它。如果看起来不是这样,我很抱歉。
      【解决方案9】:

      随着 Java 1.8 的引入,流在解决此类问题方面非常有用:

      Comparator <DateTime> myComparator = (arg1, arg2) 
                      -> {
                          if(arg1.lt(arg2)) 
                             return -1;
                          else if (arg1.lteq(arg2))
                             return 0;
                          else
                             return 1;
                         };
      
      ArrayList<DateTime> sortedList = myList
                         .stream()
                         .sorted(myComparator)
                         .collect(Collectors.toCollection(ArrayList::new));
      

      【讨论】:

        【解决方案10】:

        这是我如何实现它的答案:

        Mylist.sort(Comparator.comparing(myClass::getStarttime));
        

        【讨论】:

        • 这对我来说就像魔术一样
        【解决方案11】:

        使用下面的方法来识别日期是否排序

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
        
        boolean  decendingOrder = true;
            for(int index=0;index<date.size() - 1; index++) {
                if(simpleDateFormat.parse(date.get(index)).getTime() < simpleDateFormat.parse(date.get(index+1)).getTime()) {
                    decendingOrder = false;
                    break;
                }
            }
            if(decendingOrder) {
                System.out.println("Date are in Decending Order");
            }else {
                System.out.println("Date not in Decending Order");
            }       
        }   
        

        【讨论】:

        • 它似乎没有回答这个问题。并且请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。今天我们在java.time, the modern Java date and time API 和它的DateTimeFormatter 中做得更好。
        【解决方案12】:

        这可能是一个旧响应,但我使用了这篇文章中的一些示例来创建一个比较器,该比较器将按列表中的一个对象(即时间戳)对HashMap&lt;String, String&gt; 中的ArrayList 进行排序。

        我有这些物品:

        ArrayList<Map<String, String>> alList = new ArrayList<Map<String, String>>();
        

        地图对象如下:

        Map<String, Object> map = new HashMap<>();
                // of course this is the actual formatted date below in the timestamp
                map.put("timestamp", "MM/dd/yyyy HH:mm:ss"); 
                map.put("item1", "my text goes here");
                map.put("item2", "my text goes here");
        

        我使用该映射在循环中使用alList.add(map) 函数将所有对象加载到数组列表中。

        现在,我创建了自己的比较器:

        import org.joda.time.DateTime;
        import org.joda.time.format.DateTimeFormat;
        import org.joda.time.format.DateTimeFormatter;
        
        import java.util.ArrayList;
        import java.util.Collections;
        import java.util.Comparator;
        import java.util.HashMap;
        import java.util.Map;
        
         public class DateSorter implements Comparator {
             public int compare(Object firstObjToCompare, Object secondObjToCompare) {
            String firstDateString = ((HashMap<String, String>) firstObjToCompare).get("timestamp");
            String secondDateString = ((HashMap<String, String>) secondObjToCompare).get("timestamp");
        
            if (secondDateString == null || firstDateString == null) {
                return 0;
            }
        
            // Convert to Dates
            DateTimeFormatter dtf = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
            DateTime firstDate = dtf.parseDateTime(firstDateString);
            DateTime secondDate = dtf.parseDateTime(secondDateString);
        
            if (firstDate.isAfter(secondDate)) return -1;
            else if (firstDate.isBefore(secondDate)) return 1;
            else return 0;
            }
        }
        

        我现在可以随时在数组上调用 Comparator,它会对我的数组进行排序,给我位置 0(列表顶部)的最新时间戳和列表末尾的最早时间戳。新帖子基本上都会放在首位。

        Collections.sort(alList, new DateSorter());
        

        这可能会对某人有所帮助,这就是我发布它的原因。考虑 compare() 函数中的返回语句。有 3 种类型的结果。如果它们相等则返回 0,如果第一个日期在第二个日期之前返回 >0,如果第一个日期在第二个日期之后返回

        【讨论】:

        • 我想对此添加评论。当然在处理数组列表时会出现“NullPointerExceptions”(给定 return 0 语句)。因此,您必须处理它们,因为每种情况都会有所不同。例如包含 0 个对象的列表将生成 NullPointerException,或者包含 1 个对象的列表!
        【解决方案13】:

        传递 ArrayList In 参数。

            private static void order(ArrayList<Object> list) {
        
            Collections.sort(list, new Comparator() {
        
                public int compare(Object o2, Object o1) {
        
                    String x1 =  o1.Date;
                    String x2 =  o2.Date;
        
                        return  x1.compareTo(x2);
        
                }
            });
        }
        

        【讨论】:

          【解决方案14】:

          Date 类已经实现了 Comparator 接口。假设您有以下课程:

          public class A {
          
              private Date dateTime;
          
              public Date getDateTime() {
                  return dateTime;
              }
          
              .... other variables
          
          }
          

          假设您有一个作为List&lt;A&gt; aList 的A 对象列表,您可以使用Java 8 的流API(下面的sn-p)轻松对其进行排序:

          import java.util.Comparator;
          import java.util.stream.Collectors;
          
          ...
          
          aList = aList.stream()
                  .sorted(Comparator.comparing(A::getDateTime))
                  .collect(Collectors.toList())
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-02-06
            • 2017-12-16
            • 1970-01-01
            • 1970-01-01
            • 2012-02-24
            • 1970-01-01
            • 2014-05-12
            • 1970-01-01
            相关资源
            最近更新 更多