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

我的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/…

#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时,以上方法才有效。明智的做法是也处理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());
  }
});


评论


好答案。为什么需要包含没有空检查的版本?有什么好处?如果第二步是正确的方法,则只能包括它,并使重要信息更具吸引力。

–amotzg
2012年9月9日14:04

两个原因-简单和快速失败。您希望代码尽可能简单,并且如果确定您的属性不应该为null,那么您可能希望代码在遇到null时尽快失败,而是传递无效数据并进一步破坏该位置引入无效数据的位置。

– Domchi
2012-09-10 15:55

如果o1或o2为null,则返回0;否则,返回0。 //此行可能会导致错误,因为返回0表示它们相等。

– tanyehzheng
13-10-17在3:03



@tanyehzheng,是的,这是令人误解的,但是请注意,用于排序的.compareTo()和.equals()之间是有区别的。这实际上取决于您希望在排序过程中如何处理null。

– Domchi
13-10-21在7:18

您应该分别检查每个日期的空值,然后根据需要进行排序(在序列的开头或末尾进行空值排序)。也就是说,如果一个日期为空而一个日期不为空,则返回1或-1。如果不这样做,则不对null进行排序,而是将它们保留在排序之前列表中的任何位置。

–droozen
2014年11月13日15:53

#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-> o.getDateTime()));

–Tunaki
16年5月18日在7:42

怎么样:list.sort(Comparator.comparing(MyObject :: getDateTime)

– whitebrow
18年4月10日在8:56

@Tunaki如何进行反向排序?

–莉莉
1月6日8:38

@lily,Collections.sort(list,Collections.reverseOrder());

– sanghavi7
9月18日晚上8:35



#3 楼

您可以使用Collections.sort方法。这是一种静态方法。您将列表和比较器传递给它。它在列表上使用了经过修改的mergesort算法。这就是为什么必须将其传递给比较器以进行配对比较的原因。
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吗?

–user393964
2011年5月8日,11:42

它修改了myList。所以它完成时排序

–helios
2011年5月8日,11:51

@Sled:download.oracle.com/javase/6/docs/api/java/util/…,java.util.Comparator)

–helios
2011年5月8日,11:51

#4 楼

list.sort(Comparator.comparing(o -> o.getDateTime()));


使用Java 8 lambda的Tunaki最佳答案IMHO

#5 楼

给定具有MyObject成员且具有DateTime方法的getDateTime(),则可以按如下所示的ArrayList对象对包含MyObject元素的DateTime进行排序:

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


评论


如果要基于当前系统时间订购该怎么办。

–User3
17年11月13日14:28



#6 楼

这是我的解决方法:

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


希望对您有所帮助。

评论


如何按日期逆转?

–僵尸
18年8月31日在11:08

#7 楼

随着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));


#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的答案非常相似且更为简洁。

–amotzg
2012年9月9日在14:22

离开了一段时间,所以没有看到响应,但是再说一次,迟到总比没有好。我认为WhiteFang回答的简洁性是它对我(当时)经验不足的Java开发人员的不利之处!我的回答中包含了类型转换,这是决定性的(至少在我看来是这样)。剩下的就是您否定了我的答案比其他答案更正确的说法?我想放开蒸汽..一切都被原谅!

– Nepaluz
2013年1月7日19:56

o.getDateTime()与键入无关,它与OP对另一个对象中包含的DateTime对象的描述有关。如果只有Date或DateTime对象是可比较的,则首先不需要比较器。

–amotzg
13年1月8日在9:47

并不是要说您的答案不正确或不那么好。我只是在寻找信息以帮助我更好地理解它。很抱歉,如果不是这样的话。

–amotzg
13年1月8日在9:51

#9 楼

使用以下方法确定日期是否已排序

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,现代Java日期和时间API及其DateTimeFormatter方面有了许多改进。

– Ole V.V.
19 Mar 7 '19 at 10:41

#10 楼

这是我如何实现的答案:
Mylist.sort(Comparator.comparing(myClass::getStarttime));


#11 楼

这可能是一个旧的响应,但是我使用了本文中的一些示例来创建一个比较器,该比较器将按列表中的一个对象(即时间戳)对ArrayListHashMap<String, String>进行排序。

我有这些对象:

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)函数将所有对象加载到数组列表中。

现在,我创建了自己的比较器: br />
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()函数中的return语句。有3种类型的结果。如果它们相等,则返回0;如果第一个日期在第二个日期之前,则返回> 0;如果第一个日期在第二个日期之后,则返回<0。如果您希望您的列表被颠倒,那么只需切换这两个return语句即可!简单=]

评论


我想对此发表评论。当然,在处理数组列表时(考虑到return 0语句)会有“ NullPointerExceptions”。因此,您将不得不处理它们,因为每种情况都会有所不同。例如,包含0个对象的列表将生成NullPointerException或包含1个对象的列表!

–布兰登
2015年11月3日,17:40

#12 楼

在参数中传递ArrayList。

    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);

        }
    });
}


#13 楼

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

public class A {

    private Date dateTime;

    public Date getDateTime() {
        return dateTime;
    }

    .... other variables

}


假设您有一个A对象列表List<A> aList,则可以使用Java 8的流API轻松对其进行排序(下面的代码段) ):

import java.util.Comparator;
import java.util.stream.Collectors;

...

aList = aList.stream()
        .sorted(Comparator.comparing(A::getDateTime))
        .collect(Collectors.toList())


#14 楼

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

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