(dari Cara untuk mengurutkan daftar objek di Jawa berdasarkan beberapa bidang )
Kode yang digunakan dalam inti ini
Menggunakan Java 8 lambda's (ditambahkan 10 April 2019)
Java 8 menyelesaikan ini dengan baik oleh lambda (meskipun Guava dan Apache Commons mungkin masih menawarkan lebih banyak fleksibilitas):
Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
.thenComparing(Report::getStudentNumber)
.thenComparing(Report::getSchool));
Terima kasih atas jawaban @ gaoagong di bawah ini .
Berantakan dan berbelit-belit: Menyortir dengan tangan
Collections.sort(pizzas, new Comparator<Pizza>() {
@Override
public int compare(Pizza p1, Pizza p2) {
int sizeCmp = p1.size.compareTo(p2.size);
if (sizeCmp != 0) {
return sizeCmp;
}
int nrOfToppingsCmp = p1.nrOfToppings.compareTo(p2.nrOfToppings);
if (nrOfToppingsCmp != 0) {
return nrOfToppingsCmp;
}
return p1.name.compareTo(p2.name);
}
});
Ini membutuhkan banyak pengetikan, pemeliharaan, dan rawan kesalahan.
Cara reflektif: Menyortir dengan BeanComparator
ComparatorChain chain = new ComparatorChain(Arrays.asList(
new BeanComparator("size"),
new BeanComparator("nrOfToppings"),
new BeanComparator("name")));
Collections.sort(pizzas, chain);
Jelas ini lebih ringkas, tetapi bahkan lebih rentan kesalahan saat Anda kehilangan referensi langsung ke bidang dengan menggunakan Strings sebagai gantinya (tidak ada typesafety, auto refactoring). Sekarang jika bidang diubah namanya, kompiler bahkan tidak akan melaporkan masalah. Selain itu, karena solusi ini menggunakan refleksi, penyortiran jauh lebih lambat.
Cara ke sana: Menyortir dengan ComparisonChain Google Guava
Collections.sort(pizzas, new Comparator<Pizza>() {
@Override
public int compare(Pizza p1, Pizza p2) {
return ComparisonChain.start().compare(p1.size, p2.size).compare(p1.nrOfToppings, p2.nrOfToppings).compare(p1.name, p2.name).result();
// or in case the fields can be null:
/*
return ComparisonChain.start()
.compare(p1.size, p2.size, Ordering.natural().nullsLast())
.compare(p1.nrOfToppings, p2.nrOfToppings, Ordering.natural().nullsLast())
.compare(p1.name, p2.name, Ordering.natural().nullsLast())
.result();
*/
}
});
Ini jauh lebih baik, tetapi membutuhkan beberapa kode pelat ketel untuk kasus penggunaan paling umum: nilai null harus dinilai lebih rendah secara default. Untuk bidang-nol, Anda harus memberikan arahan ekstra untuk Jambu apa yang harus dilakukan dalam kasus itu. Ini adalah mekanisme yang fleksibel jika Anda ingin melakukan sesuatu yang spesifik, tetapi sering kali Anda menginginkan case default (mis. 1, a, b, z, null).
Mengurutkan dengan Apache Commons CompareToBuilder
Collections.sort(pizzas, new Comparator<Pizza>() {
@Override
public int compare(Pizza p1, Pizza p2) {
return new CompareToBuilder().append(p1.size, p2.size).append(p1.nrOfToppings, p2.nrOfToppings).append(p1.name, p2.name).toComparison();
}
});
Seperti Guava's ComparisonChain, kelas pustaka ini mengurutkan dengan mudah pada beberapa bidang, tetapi juga mendefinisikan perilaku default untuk nilai-nilai nol (mis. 1, a, b, z, null). Namun, Anda tidak dapat menentukan hal lain juga, kecuali jika Anda menyediakan Pembanding Anda sendiri.
Jadi
Pada akhirnya itu turun ke rasa dan kebutuhan akan fleksibilitas (Guava's ComparisonChain) vs kode ringkas (Apache's CompareToBuilder).
Metode bonus
Saya menemukan solusi yang bagus yang menggabungkan beberapa komparator dengan urutan prioritas pada CodeReview di MultiComparator
:
class MultiComparator<T> implements Comparator<T> {
private final List<Comparator<T>> comparators;
public MultiComparator(List<Comparator<? super T>> comparators) {
this.comparators = comparators;
}
public MultiComparator(Comparator<? super T>... comparators) {
this(Arrays.asList(comparators));
}
public int compare(T o1, T o2) {
for (Comparator<T> c : comparators) {
int result = c.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
public static <T> void sort(List<T> list, Comparator<? super T>... comparators) {
Collections.sort(list, new MultiComparator<T>(comparators));
}
}
Koleksi Apache Commons Ofcourse sudah memiliki kegunaan untuk ini:
ComparatorUtils.chainedComparator (comparatorCollection)
Collections.sort(list, ComparatorUtils.chainedComparator(comparators));