web-dev-qa-db-ja.com

プロパティによるカスタムオブジェクトのArrayListの並べ替え

私はComparatorを使ってArrayListsをソートすることについて読みましたが、すべての例で人々はcompareToを使っていました。

カスタムオブジェクトのArrayListをそのプロパティの1つであるDateオブジェクト(getStartDay())でソートしたいと思いました。通常、私はそれらをitem1.getStartDate().before(item2.getStartDate())で比較しているので、以下のように書くことができるかどうか疑問に思いました。

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}

public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}
1020
Samuel

Datename__ implements Comparablename__ を実装しているので、compareToname__メソッドと同じようにStringname__メソッドがあります。

だからあなたのカスタムの Comparatorname__ はこのようになるでしょう:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

compare()メソッドはintname__を返す必要があるため、とにかく計画していたように直接booleanname__を返すことはできません。

あなたのソートコードはあなたが書いたようなものです。

Collections.sort(Database.arrayList, new CustomComparator());

コンパレータを再利用する必要がない場合、これらすべてを記述するための少し短い方法は、インラインの無名クラスとして記述することです。

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

から Java-8

Comparatorname__に ラムダ式 を使用することで、最後の例を短い形式で書くことができます。

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

そしてListname__には sort(Comparator) メソッドがあるので、これをさらに短くすることができます。

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

これは 組み込みメソッド のような一般的な慣用句です - /Comparatorname__キーを持つクラスのComparablename__を生成する:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

これらはすべて同等の形式です。

1396
Michael Myers

自然なソート順(例としてクラスNumber)を持つクラスはComparableインターフェースを実装する必要がありますが、自然なソート順を持たないクラス(例としてクラスChair)はComparator(または匿名のComparator)で提供されるべきですクラス)。

2つの例

public class Number implements Comparable<Number> {
    private int value;

    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}

public class Chair {
    private int weight;
    private int height;

    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

使用法:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});
189
Björn

ArrayListをソートするには、次のコードスニペットを使うことができます。

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});
153
user1377710

はい、できます。項目の比較には2つのオプション、 Comparable インターフェイス、および Comparator インターフェイスがあります。

これらのインタフェースはどちらも異なる動作を可能にします。 Comparableを使用すると、オブジェクトをStringと同じように動作させることができます(実際、StringはComparableを実装しています)。第二に、コンパレータは、あなたがしたいことをあなたがすることができます。あなたはこのようにするでしょう:

Collections.sort(myArrayList, new MyComparator());

これにより、Collections.sortメソッドは、ソートメカニズムとしてコンパレータを使用します。 ArrayList内のオブジェクトが同等のものを実装している場合は、代わりに次のようなことを実行できます。

Collections.sort(myArrayList);

Collections クラスには、これらの便利で一般的なツールが多数含まれています。

41
aperkins

Java 8ラムダ式

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

OR

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)
36
Sorter

Java 8では、コンパレータにメソッド参照を使用できます。

import static Java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));
29
assylias
import Java.text.ParseException;
import Java.text.SimpleDateFormat;
import Java.util.ArrayList;
import Java.util.Collections;
import Java.util.Comparator;
import Java.util.Date;

public class test {

public static class Person {
    public String name;
    public int id;
    public Date hireDate;

    public Person(String iname, int iid, Date ihireDate) {
        name = iname;
        id = iid;
        hireDate = ihireDate;
    }

    public String toString() {
        return name + " " + id + " " + hireDate.toString();
    }

    // Comparator
    public static class CompId implements Comparator<Person> {
        @Override
        public int compare(Person arg0, Person arg1) {
            return arg0.id - arg1.id;
        }
    }

    public static class CompDate implements Comparator<Person> {
        private int mod = 1;
        public CompDate(boolean desc) {
            if (desc) mod =-1;
        }
        @Override
        public int compare(Person arg0, Person arg1) {
            return mod*arg0.hireDate.compareTo(arg1.hireDate);
        }
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
    ArrayList<Person> people;
    people = new ArrayList<Person>();
    try {
        people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
        people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
        people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Collections.sort(people, new Person.CompId());
    System.out.println("BY ID");
    for (Person p : people) {
        System.out.println(p.toString());
    }

    Collections.sort(people, new Person.CompDate(false));
    System.out.println("BY Date asc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(true));
    System.out.println("BY Date desc");
    for (Person p : people) {
        System.out.println(p.toString());
    }

}

}
13
CharlesW

技術は日々出現しているので、その答えは時間とともに変わるでしょう。私はLambdaJを見ましたが、とても興味深いようです。

あなたはこれらのタスクをLambdaJで解くことができます。あなたはそれをここで見つけることができます: http://code.google.com/p/lambdaj/ /

ここに例があります:

ソート順

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
});

ラムダでソート

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

もちろん、このような美しさを持つことはパフォーマンスに影響します(平均2倍)が、もっと読みやすいコードを見つけることができますか?

13
Federico Piazza

Java 8で最も簡単な方法は英語のアルファベット順になることです

クラス実装

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

並べ替え

  Collections.sort(Your List);

英語以外の文字を含むアルファベットでソートしたい場合は、ロケールを使用できます。

クラス実装

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));



   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

並べ替え

Collections.sort(your array list,new NewspaperClass());
9
Beyaz

Java 8以降からは、Collections.sort()を直接使用する必要はありません。 Listインターフェースにはデフォルトのsort()メソッドがあります。

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

http://visvv.blogspot.in/2016/01/sorting-objects-in-Java-8.html を参照してください。

6

関数とメソッドの参照

Collections.sort メソッドは、 List を使用して、 Comparator をソートできます。そのComparatorComparator.comparing メソッドを使用して実装できます。ここで、必要な Function として メソッド参照 を渡すことができます。幸い、実際のコードはこの説明よりもはるかに単純で短いです。

Java 8の場合

Collections.sort(list, comparing(ClassName::getName));

または

Collections.sort(list, comparing(ClassName::getName).reversed());

もう一つの方法は

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
6
Arun

Java 8 Lambdaはソートを短縮します。

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
5
javasenior

あなたはGuavaを試すことができます 注文

Function<Item, Date> getStartDate = new Function<Item, Date>() {
    public Date apply(Item item) {
        return item.getStartDate();
    }
};

List<Item> orderedItems = Ordering.natural().onResultOf(getStartDate).
                          sortedCopy(items);
5

あなたはJava 8を使ってソートすることができます

yourList.sort(Comparator.comparing(Classname::getName));

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
5
Seeker

Bean Comparator を使用すると、カスタムクラスの任意のプロパティをソートできます。

5
camickr

はい、それは可能です この答え 私はクラスvのプロパティIndexValueでソート 

    // Sorting by property v using a custom comparator.
    Arrays.sort( array, new Comparator<IndexValue>(){
        public int compare( IndexValue a, IndexValue b ){
            return a.v - b.v;
        }
    });

ここに気付いたら、私は 無名内部クラス (これはクロージャのためのJavaです)を作成し、それをクラスsortArraysメソッドに直接渡します。 

あなたのオブジェクトはComparableも実装するかもしれません(それはStringやJavaのコアライブラリのほとんどがしていることです)が、それはそれ自身がクラスの "自然なソート順"を定義するでしょう。

5
OscarRyz

私は、これらの答えのすべてが、比較可能なものを実装するため、または比較可能なヘルパーを持つために、基礎となるクラス(Object)に依存しているにもかかわらず、ほとんど見つけました。

私の解決策ではありません!次のコードでは、文字列名を知ることでオブジェクトのフィールドを比較できます。名前を使用しないように簡単に変更することもできますが、その場合は名前を公開するか、比較対象のオブジェクトを1つ作成する必要があります。

Collections.sort(anArrayListOfSomeObjectPerhapsUsersOrSomething, new ReflectiveComparator(). new ListComparator("name"));

public class ReflectiveComparator {
    public class FieldComparator implements Comparator<Object> {
        private String fieldName;

        public FieldComparator(String fieldName){
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);

                Comparable object1FieldValue = (Comparable) field.get(object1);
                Comparable object2FieldValue = (Comparable) field.get(object2);

                return object1FieldValue.compareTo(object2FieldValue);
            }catch (Exception e){}

            return 0;
        }
    }

    public class ListComparator implements Comparator<Object> {
        private String fieldName;

        public ListComparator(String fieldName) {
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable o1FieldValue = (Comparable) field.get(object1);
                Comparable o2FieldValue = (Comparable) field.get(object2);

                if (o1FieldValue == null){ return -1;}
                if (o2FieldValue == null){ return 1;}
                return o1FieldValue.compareTo(o2FieldValue);
            } catch (NoSuchFieldException e) {
                throw new IllegalStateException("Field doesn't exist", e);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Field inaccessible", e);
            }
        }
    }
}
4
Kevin Parker

このコードスニペットは役に立つかもしれません。あなたがObject をソートしたいのであれば、VolumeNameでソートしたいです。

public List<Volume> getSortedVolumes() throws SystemException {
    List<Volume> volumes = VolumeLocalServiceUtil.getAllVolumes();
    Collections.sort(volumes, new Comparator<Volume>() {
        public int compare(Volume o1, Volume o2) {
            Volume p1 = (Volume) o1;
            Volume p2 = (Volume) o2;
            return p1.getVolumeName().compareToIgnoreCase(
                    p2.getVolumeName());
        }
    });
    return volumes;
}

これはうまくいきます。私は私のjspでそれを使います。

3
Laura Liparulo

2016年にドイツのシュトゥットガルトで開催されるJavaフォーラムで、この presentation holdをご覧ください。

ほんの少しのスライドがドイツ語を使います、内容の99%は「英語ベースの」Javaソースコードです。好き

someCollection.sort(
  OurCustomComparator
    .comparing(Person::getName)
    .thenComparing(Person::getId)
);

OurCustomComparatorはデフォルトのメソッド(およびその他の興味深いアイデア)を使用しています。示されているように、ソート用のいくつかの取得メソッドを選択するための非常に簡潔なコードにつながります。ソート基準の非常に単純な連鎖(または逆転)。 

あなたがJava8に慣れているなら、あなたは始めるためにそこにたくさんの資料を見つけます。

3
GhostCat

customComparatorクラスは、使用するためにJava.util.Comparatorを実装する必要があります。また、compare()AND equals()をオーバーライドする必要があります。

compare()は次の質問に答えなければなりません。オブジェクト1はオブジェクト2よりも小さいか、等しいか、それとも大きいか?

フルドキュメント: http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Comparator.html

2
Vinny

このライブラリで ここ カスタムオブジェクトのリストを複数の列にソートすることができます。このライブラリはバージョン8.0の機能を使用しています。サンプルもあります。これはするべきサンプルです

SortKeys sortKeys = new SortKeys();
sortKeys.addField("firstName")
            .addField("age", true); // This (true) will sort the age descending

// Other ways to specify a property to the sorter are
//      .addField("lastName", String.class);
//      .addField("dob", Date.class, true);

// Instantiate a ListSorter
ListSorter listSorter = new ListSorter();

// Pass the data to sort (listToSort) and the "by keys" to sort (sortKeys)
List sortedList = (List<Person>) listSorter.sortList(listToSort, sortKeys);
2
Shriram M.

1.8以降の新機能は、Collection.sort()を使用する代わりにList.sort()メソッドを使用するため、直接mylistcontainer.sort()を呼び出す

これがList.sort()機能を示すコードスニペットです。

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));

// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]

// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

フルーツクラスは:

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;

    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }

    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }

    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   
2
Norbert

私はこのプロセスが好きです。

public class SortUtil
{    
    public static <T> List<T> sort(List<T> list, String sortByProperty)
    {
            Collections.sort(list, new BeanComparator(sortByProperty));
            return list;
    }
}

List<T> sortedList = SortUtil<T>.sort(unsortedList, "startDate");

オブジェクトのリストにstartDateというプロパティがある場合は、use thisを繰り返し呼び出します。 startDate.timeをチェーンすることもできます。

これはあなたのオブジェクトがComparableであることを必要とします、それはあなたがcompareToequals、そしてhashCode実装を必要とすることを意味します。

はい、それはより速いかもしれません...しかし今、あなたはそれぞれの種類の種類のために新しいComparatorを作る必要はありません。もしあなたが開発時間を節約して実行時にあきらめることができるなら、あなたはこれで行くかもしれません。

1
DDus

Java 8を使うと、Comparator.comparing()を使ってComparatorを一行で定義できます

次のいずれかの方法を使用してください。

オプション1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

オプション2:

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));
0
Sahil Chhabra

カスタムクラスは、CompareToメソッドの実装を必要とする「Comparable」インターフェイスを実装できます。 CompareToメソッドでは、オブジェクトが他のオブジェクトよりも小さいか、大きいかを定義できます。したがって、あなたの例では、次のようになります。

public class MyCustomClass implements Comparable<MyCustomClass>{

..........

 @Override
public int compareTo(MyCustomClass a) {
    if(this.getStartDate().before(a.getStartDate())){
        return -1;
    }else if(a.getStartDate().before(this.getStartDate())){
        return 1;
    }else {
        return 0;
    }
}

負の数は、thisが比較対象のオブジェクトよりも小さいことを示します。正の数は、thisがオブジェクトと比較して大きいことを示し、ゼロはオブジェクトが等しいことを意味します。

その後、collections.sort(myList)を使用して、コンパレータに入力することなくリストをソートできます。このメソッドには、TreeSetやTreeMapなどのソートされたコレクションデータ構造を使用する場合、自動的にソートされるという利点もあります。

Comparableインターフェースについて詳しく知りたい場合は、この記事を確認してください(開示:私は著者です;)) https://nullbeans.com/the-Java-comparable-interface-automatic-sort- of-collections /

0
A.Ebrahim