web-dev-qa-db-ja.com

オブジェクトのコレクションを並べ替える

文字列の単純なリストがある場合:

List<String> stringList = new ArrayList<String>();

私はそれを並べ替えることができます:

Collections.sort(stringList);

しかし、私にはPersonクラスがあるとします:

public class Person
{
   private String name;
   private Integer age;
   private String country;
}

そしてそのリスト:

List<Person> personList = new ArrayList<Person>();

また、名前、年齢、国ごとに並べ替えたいと思います。

それを達成する最も簡単な方法は何ですか?

Comparableインターフェースを実装できることは知っていますが、特定の1つのプロパティでソートすることを制限しているようです。

58
Knut Arne Vedaa

Comparator インターフェースを実装し(異なるソート順序ごとに1回)、Comparatorを追加パラメーターとして受け取る Collections.sort() メソッドを使用します。

35

Collections.sortは、カスタムコンパレータで呼び出すことができます。そして、そのコンパレーターを実装して、異なるソート順でソートできるようにすることができます。次に例を示します(Personモデルの場合-年齢を整数として):

public class FlexiblePersonComparator implements Comparator<Person> {
  public enum Order {Name, Age, Country}

  private Order sortingBy = Name;

  @Override
  public int compare(Person person1, Person person2) {
    switch(sortingBy) {
      case Name: return person1.name.compareTo(person2.name);
      case Age: return person1.age.compareTo(person2.age);
      case Country: return person1.country.compareTo(person2.country);
    }
    throw new RuntimeException("Practically unreachable code, can't be thrown");
  }

  public void setSortingBy(Order sortBy) {
    this.sortingBy = sortingBy;
  }
}

そして、あなたはそれをそのように使用します(人がフィールドであると仮定します):

public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) {
  List<Person> persons = this.persons;  // useless line, just for clarification
  FlexiblePersonComparator comparator = new FlexiblePersonComparator();
  comparator.setSortingBy(sortingBy);
  Collections.sort(persons, comparator); // now we have a sorted list
}
48
Andreas_D

レスポンダーに感謝します。他の人のために、完全な例を含めたいと思います。

解決策は、次の追加クラスを作成することです。

public class NameComparator implements Comparator<Person>
{
    public int compare(Person o1, Person o2)
    {
       return o1.getName().compareTo(o2.getName());
   }
}

public class AgeComparator implements Comparator<Person>
{
    public int compare(Person o1, Person o2)
    {
        return o1.getAge().compareTo(o2.getAge());
    }
}

public class CountryComparator implements Comparator<Person>
{
    public int compare(Person o1, Person o2)
    {
        return o1.getCountry().compareTo(o2.getCountry());
    }
}

リストは次のようにソートできます。

Collections.sort(personList, new NameComparator());
Collections.sort(personList, new AgeComparator());
Collections.sort(personList, new CountryComparator());
17
Knut Arne Vedaa

Java 8これを行う8つの方法は、次のように _List.sort_ を使用することです。

_personList.sort(Comparator.comparing(Person::getName));
_

スチュアートマークス を引用する ここ に対する彼の答え。

これは、List.sort(cmp)よりもCollections.sort(list, cmp)拡張メソッドの大きな利点です。これは、myList.sort(cmp)の代わりにCollections.sort(myList, cmp)を記述できるという小さな構文上の利点にすぎないように思えるかもしれません。違いは、インターフェイス拡張メソッドであるmyList.sort(cmp)は、特定のList実装によってオーバーライドできることです。たとえば、ArrayList.sort(cmp)Arrays.sort()を使用してインプレースでリストをソートしますが、デフォルトの実装では古いcopyout-sort-copybackテクニックを実装します。

10
aioobe

次のように、Apache commons beanutilsの BeanComparator を使用することもできます。

Collections.sort(personList, new BeanComparator("name"));
6
Jörn Horstmann

3種類のコンパレータを実装します。

ソートコマンドにコンパレータを追加できます。定義するコンパレータは、名前、年齢、その他の要素で要素をソートします。

Collections.sort(list, new Comparator() {

        public int compare(Object arg0, Object arg1) {
            if (!(arg0 instanceof Person)) {
                return -1;
            }
            if (!(arg1 instanceof Person)) {
                return -1;
            }

            Person pers0 = (Person)arg0;
            Person pers1 = (Person)arg1;


            // COMPARE NOW WHAT YOU WANT
            // Thanks to Steve Kuo for your comment!
            return pers0.getAge() - pers1.getAge();
        }
    });
3
Markus Lausberg

Collections.sortメソッドは、使用するコンパレーターである2番目の引数で呼び出すことができます。 3つのコンパレーターを作成し、適切なときに必要なコンパレーターを使用します。

Collections.sort(list , new Comparator() {
        public int compare(Object o1, Object o2) {
          ...
        }
      });
2
z5h

Lambdaj( http://code.google.com/p/lambdaj/ )を使用すると、次の方法で求めていることを実現できます。

sort(personList、on(Person.class).getName());

sort(personList、on(Person.class).getAge());

sort(personList、on(Person.class).getCountry());

0
Mario Fusco

非常によく似た質問 (並べ替えではなく検索について)を尋ねましたが、おそらくいくつかの有用な情報があります(最終的にenumを実装するComparatorを使用して、コンパレータセレクタとしてのenum値)。

0
Jason S