1239

Comparator を使用して ArrayLists をソートすることについて読みましたが、人々が使用したすべての例で、compareToいくつかの調査によると Strings のメソッドです。

カスタム オブジェクトの 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);
    ...
}
4

29 に答える 29

1669

Dateを実装しているのでComparable、それとcompareTo同じようにメソッドStringがあります。

したがって、カスタムComparatorは次のようになります。

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

compare()メソッドは を返さなければならないので、とにかく計画していintたように直接返すことはできませんでした。boolean

あなたのソートコードは、あなたが書いたものとほぼ同じです:

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

以降

のラムダ式を使用して、最後の例を短い形式で記述できるようになりましたComparator

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

Listメソッドがあるため、sort(Comparator)これをさらに短縮できます。

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

これは非常に一般的なイディオムであるため、キーを持つクラスの を生成する組み込みメソッドがあります。ComparatorComparable

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

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

于 2010-05-06T21:18:23.063 に答える
198

自然順順のクラス(例としてクラス番号)はComparableインターフェースを実装する必要がありますが、自然順順のないクラス(例としてクラスチェア)にはコンパレーター(または匿名のコンパレーター)を提供する必要があります。クラス)。

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) {
        ...
    }
});
于 2010-05-06T21:45:27.547 に答える
162

を並べ替えるにはArrayList、次のコード スニペットを使用できます。

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});
于 2012-05-06T13:50:54.777 に答える
46

JAVA 8 ラムダ式

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

また

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)
于 2014-09-05T13:10:20.577 に答える
44

はい、できます。アイテムの比較には、ComparableインターフェイスとComparatorインターフェイスの 2 つのオプションがあります。

これらのインターフェイスはどちらも、異なる動作を可能にします。Comparable を使用すると、先ほど説明した String のようにオブジェクトを動作させることができます (実際、String は Comparable を実装しています)。2 番目の Comparator は、ユーザーが求めていることを実行できるようにします。次のようにします。

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

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

Collections.sort(myArrayList);

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

于 2010-05-06T21:17:40.397 に答える
13
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());
    }

}

}
于 2012-04-03T15:32:34.090 に答える
9

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());
于 2016-05-28T12:11:40.810 に答える
9

関数とメソッドのリファレンス

このメソッドは、パスを使用してCollections.sortソートできます。これは、必要に応じてメソッド参照を渡すことができるメソッドを使用して実装できます。幸いなことに、実際のコードはこの説明よりもはるかに単純で短いものです。ListComparatorComparatorComparator.comparingFunction

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())));
于 2015-12-15T00:37:50.700 に答える
7

Java 8を使用してソートできます

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

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
于 2016-09-06T04:26:37.420 に答える
6

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

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を参照してください。

于 2016-01-03T06:58:59.183 に答える
6

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

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
于 2015-09-09T14:18:12.750 に答える
5

これらの回答のすべてではないにしても、そのほとんどは、基になるクラス (オブジェクト) に依存して、同等のものを実装するか、同等のヘルパー インターフェイスを持つことがわかりました。

私の解決策ではありません!次のコードでは、文字列名を知ることでオブジェクトのフィールドを比較できます。名前を使用しないように簡単に変更できますが、それを公開するか、比較するオブジェクトの 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);
            }
        }
    }
}
于 2012-04-25T19:28:41.087 に答える
5

Guava Orderingを試すことができます:

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);
于 2013-03-16T23:06:15.253 に答える
5

Bean Comparatorを使用して、カスタム クラスの任意のプロパティを並べ替えることができます。

于 2010-05-06T21:29:16.000 に答える
5

はい、それは可能ですたとえば、この回答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;
        }
    });

ここで気付いた場合は、匿名の内部クラスsort(クロージャの Java) を作成し、それをクラスのメソッドに直接渡しています。Arrays

あなたのオブジェクトは実装することもできますComparable(これは String と Java のほとんどのコア ライブラリが行うことです) が、それはクラス自体の「自然な並べ替え順序」を定義し、新しいものをプラグインすることはできません。

于 2010-05-06T21:29:28.823 に答える
3

このコードスニペットは役立つ場合があります。私の場合、オブジェクトを並べ替える場合は、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でそれを使用しています。

于 2013-02-04T11:29:42.150 に答える
3

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

compare() は、オブジェクト 1 がオブジェクト 2 より小さいか、等しいか、または大きいかという質問に答える必要があります。

完全なドキュメント: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html

于 2010-05-06T21:20:17.160 に答える
3

Java 8以前のバージョンを使用している場合、これが最善の解決策です。

Collections.sort(studentList, Comparator.comparing(Student::getCgpa).reversed().thenComparing(Student:: getFname).thenComparing(Student::getId));

この場合、最初に「getCgpa」でソートされ、2 番目の部分では getFname と getId でソートされます。これは pojo クラスのフィールドです。

于 2020-07-17T01:01:15.317 に答える
1

私はこのプロセスを好みます:

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、これを何度も呼び出します。それらをチェーンすることもできますstartDate.time

これには、オブジェクトが でComparableある必要があります。つまり、compareToequals、およびhashCode実装が必要です。

はい、もっと高速になる可能性があります...しかし、ソートの種類ごとに新しい Comparator を作成する必要はありません。開発時間を節約してランタイムをあきらめることができる場合は、これを使用することをお勧めします。

于 2010-05-06T23:43:30.063 に答える