ArrayList内のオブジェクトを日付で並べ替えますか?


149

私が見つけるすべての例は、これをアルファベット順に行うことに関するものですが、要素を日付でソートする必要があります。

私のArrayListには、データメンバーの1つがDateTimeオブジェクトであるオブジェクトが含まれています。DateTimeで関数を呼び出すことができます。

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

だから比較するために私は次のようなことをすることができます:

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

ifブロック内で何をすればよいですか?


3
私は解決策を投稿しましたが、注文に関する洞察を得たい場合は、注文アルゴリズム(バブルソート、マージソート、クイックソートなど)を読む必要があります。
helios、

おかげで、それらを見てみましょう。ソートについては何も知りません

いくつかの有用なJavaの1.8ソリューションは、このスレッドで見つけることができます。stackoverflow.com/questions/36361156/...
lradacher

回答:


417

オブジェクトを比較可能にすることができます:

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を回避するためにnullも処理するのが賢明です。

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

または2番目の例では:

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

1
いい答えだ。nullチェックなしのバージョンを含める必要があるのはなぜですか?利点は何ですか?正しい方法が2番目の場合は、それを含めて、重要な情報をより魅力的にすることができます。
amotzg 2012

17
2つの理由-シンプルさとフェイルファスト。コードをできるだけ単純にし、プロパティがnullでないことが確実な場合は、nullが発生した場合にできるだけ早くコードを失敗させ、無効なデータを渡してさらにその場所から離れるようにする必要がある無効なデータが導入された場所。
Domchi、2012

3
o1またはo2がnullの場合、0を返します。//この行は、0を返すとそれらが等しいことを意味するため、バグを引き起こす可能性があります。
tanyehzheng 2013年

@tanyehzheng、正解です。誤解を招きますが、並べ替えに使用される.compareTo()と.equals()には違いがあることに注意してください。これは、並べ替え中にnullをどのように処理するかによって異なります。
Domchi 2013年

1
各日付のnullを個別に確認し、必要に応じて並べ替える必要があります(nullはシーケンスの先頭または末尾で並べ替えます)。つまり、1つの日付がnullでもう1つがnullでない場合、1または-1を返します。これを行わないと、nullは並べ替えられず、並べ替え前にリストのどこかにあるままになります。
droozen、2014年

64

Java 8以降、Listインターフェースはsortメソッドを提供しますラムダ式と組み合わせると、最も簡単な解決策は

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

8
さらに良いでしょうlist.sort(Comparator.comparing(o -> o.getDateTime()));
Tunaki

21
これはどうですか:list.sort(Comparator.comparing(MyObject::getDateTime)
ホワイトブロウ2018

@Tunaki逆ソートの方法は?
リリー

18

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など)である場合は、コンパレーターを省略でき、自然順序付けが使用されます。


1
そして、これはそれが完了したときにmyListを返しますか?

myListを変更します。したがって、終了時にソートされます
helios



8

与えられ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

5

これは私が解決した方法です:

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

お役に立てば幸いです。


日付で逆にする方法は?
ゾンビ

2

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

1

ここで私が見つけたすべての回答は、単純な問題に対しては必ずしも複雑ではないことがわかりました(少なくとも経験豊富な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]));
    }
});

6
あなたの答えは、ここで他の答えよりも複雑ではなく、より正確ですか?私の意見では、たとえばWhiteFang32の答えは非常によく似ていて簡潔です。
amotzg 2012

しばらく離れていたので、反応は見られませんでしたが、それでも、遅くなることはありません。WhiteFangの答えの簡潔さは、(当時の)経験の浅いJava開発者の目にとっての欠点だったと思います!私の応答にタイプキャストを含めることはクリンチャーでした(少なくとも私の心では)。残っているのは、私の答えが他の答えよりも正しいという主張を引き抜いたところです。蒸気を放出することは私が思う..すべては許される!
ネパール2013年

o.getDateTime()は入力に関するものではなく、DateTime別のオブジェクト内に含まれるオブジェクトのOPの説明に関するものです。それだけであるDateDateTimeオブジェクトであるComparable場合、そもそもの必要はありませんでしたComparator
amotzg 2013年

あなたの答えがあまり正確ではないか、そうでなければあまり良くないと言うつもりはありませんでした。私はそれをよりよく理解するのに役立つ情報を探していました。それ以外のように思われた場合は申し訳ありません。
amotzg 2013年

0

これは、古いレスポンスかもしれないが、私は、並べ替えますコンパレータ作成するには、この記事からいくつかの例を使用ArrayListするとHashMap<String, String>、タイムスタンプされていることを、リスト内の1つのオブジェクトでは。

私はこれらのオブジェクトを持っています:

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

これで、配列でいつでもコンパレータを呼び出すだけで配列をソートし、位置0(リストの最上部)の最新のタイムスタンプとリストの最後の最も早いタイムスタンプを取得できます。新しい投稿は基本的にトップに置かれます。

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

これは誰かを助けるかもしれません、それが私がそれを投稿した理由です。compare()関数内のreturnステートメントを考慮してください。結果には3つのタイプがあります。等しい場合は0を返し、最初の日付が2番目の日付より前の場合は> 0を返し、最初の日付が2番目の日付より後である場合は<0を返します。リストを逆にしたい場合は、これら2つのreturnステートメントを切り替えるだけです!シンプル=]


これについてコメントを付けたかった。もちろん、(return 0ステートメントを指定すると)配列リストを処理するときに「NullPointerExceptions」があります。したがって、それぞれのケースが異なるため、それらを処理する必要があります。たとえば、オブジェクトが0のリストはNullPointerExceptionを生成します。または、オブジェクトが1つのリストを生成します。
ブランドン、

0

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

        }
    });
}

0

以下のアプローチを使用して、日付がソートされているかどうかを識別します

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

1
質問に答えていないようです。そして、若い人たちに長く古くて悪名高い面倒なSimpleDateFormatクラスを使うように教えないでください。少なくとも最初の選択肢としてではない。予約なしではありません。今日、私たちはjava.time最新のJavaの日付と時刻のAPIとそのをはるかに上回っていますDateTimeFormatter
Ole VV

0

DateクラスはすでにComparatorインターフェースを実装しています。あなたが以下のクラスを持っていると仮定します:

public class A {

    private Date dateTime;

    public Date getDateTime() {
        return dateTime;
    }

    .... other variables

}

また、AオブジェクトのリストがList<A> aListであるとします。Java8のストリームAPI(以下のスニペット)で簡単に並べ替えることができます。

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

...

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

-1

将来のビューア、これが最も簡単な解決策だと思います。モデルに文字列型の日付(たとえば、 "2020-01-01 10:00:00")が含まれている場合は、次の行を記述して、日付の降順でデータを並べ替えます新しいものから古いものへ:

Collections.sort(messages, (o1, o2) -> o2.getMessageDate().compareTo(o1.getMessageDate()));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.