私は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);
...
}
Date
name__ implements Comparable
name__ を実装しているので、compareTo
name__メソッドと同じようにString
name__メソッドがあります。
だからあなたのカスタムの Comparator
name__ はこのようになるでしょう:
public class CustomComparator implements Comparator<MyObject> {
@Override
public int compare(MyObject o1, MyObject o2) {
return o1.getStartDate().compareTo(o2.getStartDate());
}
}
compare()
メソッドはint
name__を返す必要があるため、とにかく計画していたように直接boolean
name__を返すことはできません。
あなたのソートコードはあなたが書いたようなものです。
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
name__に ラムダ式 を使用することで、最後の例を短い形式で書くことができます。
Collections.sort(Database.arrayList,
(o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
そしてList
name__には sort(Comparator)
メソッドがあるので、これをさらに短くすることができます。
Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));
これは 組み込みメソッド のような一般的な慣用句です - /Comparator
name__キーを持つクラスのComparable
name__を生成する:
Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));
これらはすべて同等の形式です。
自然なソート順(例としてクラス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) {
...
}
});
ArrayList
をソートするには、次のコードスニペットを使うことができます。
Collections.sort(studList, new Comparator<Student>(){
public int compare(Student s1, Student s2) {
return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
}
});
はい、できます。項目の比較には2つのオプション、 Comparable インターフェイス、および Comparator インターフェイスがあります。
これらのインタフェースはどちらも異なる動作を可能にします。 Comparableを使用すると、オブジェクトをStringと同じように動作させることができます(実際、StringはComparableを実装しています)。第二に、コンパレータは、あなたがしたいことをあなたがすることができます。あなたはこのようにするでしょう:
Collections.sort(myArrayList, new MyComparator());
これにより、Collections.sortメソッドは、ソートメカニズムとしてコンパレータを使用します。 ArrayList内のオブジェクトが同等のものを実装している場合は、代わりに次のようなことを実行できます。
Collections.sort(myArrayList);
Collections クラスには、これらの便利で一般的なツールが多数含まれています。
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)
Java 8では、コンパレータにメソッド参照を使用できます。
import static Java.util.Comparator.comparing;
Collections.sort(list, comparing(MyObject::getStartDate));
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());
}
}
}
技術は日々出現しているので、その答えは時間とともに変わるでしょう。私は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倍)が、もっと読みやすいコードを見つけることができますか?
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());
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 を参照してください。
Collections.sort
メソッドは、 List
を使用して、 Comparator
をソートできます。そのComparator
は Comparator.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())));
Java 8 Lambdaはソートを短縮します。
Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
あなたは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);
あなたはJava 8を使ってソートすることができます
yourList.sort(Comparator.comparing(Classname::getName));
or
yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
Bean Comparator を使用すると、カスタムクラスの任意のプロパティをソートできます。
はい、それは可能です この答え 私はクラス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です)を作成し、それをクラスsort
のArrays
メソッドに直接渡します。
あなたのオブジェクトはComparable
も実装するかもしれません(それはStringやJavaのコアライブラリのほとんどがしていることです)が、それはそれ自身がクラスの "自然なソート順"を定義するでしょう。
私は、これらの答えのすべてが、比較可能なものを実装するため、または比較可能なヘルパーを持つために、基礎となるクラス(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);
}
}
}
}
このコードスニペットは役に立つかもしれません。あなたが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でそれを使います。
2016年にドイツのシュトゥットガルトで開催されるJavaフォーラムで、この presentation holdをご覧ください。
ほんの少しのスライドがドイツ語を使います、内容の99%は「英語ベースの」Javaソースコードです。好き
someCollection.sort(
OurCustomComparator
.comparing(Person::getName)
.thenComparing(Person::getId)
);
OurCustomComparator
はデフォルトのメソッド(およびその他の興味深いアイデア)を使用しています。示されているように、ソート用のいくつかの取得メソッドを選択するための非常に簡潔なコードにつながります。ソート基準の非常に単純な連鎖(または逆転)。
あなたがJava8に慣れているなら、あなたは始めるためにそこにたくさんの資料を見つけます。
customComparatorクラスは、使用するためにJava.util.Comparatorを実装する必要があります。また、compare()AND equals()をオーバーライドする必要があります。
compare()は次の質問に答えなければなりません。オブジェクト1はオブジェクト2よりも小さいか、等しいか、それとも大きいか?
フルドキュメント: http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Comparator.html
このライブラリで ここ カスタムオブジェクトのリストを複数の列にソートすることができます。このライブラリはバージョン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);
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
私はこのプロセスが好きです。
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
であることを必要とします、それはあなたがcompareTo
、equals
、そしてhashCode
実装を必要とすることを意味します。
はい、それはより速いかもしれません...しかし今、あなたはそれぞれの種類の種類のために新しいComparatorを作る必要はありません。もしあなたが開発時間を節約して実行時にあきらめることができるなら、あなたはこれで行くかもしれません。
Java 8を使うと、Comparator.comparing()
を使ってComparator
を一行で定義できます
次のいずれかの方法を使用してください。
オプション1:
listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));
オプション2:
Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));
カスタムクラスは、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 /