(orijinal olarak Java'daki nesne listelerini birden çok alana göre sıralamanın Yolları'ndan )
Bu temelde orijinal çalışma kodu
Java 8 lambda'yı kullanma (10 Nisan 2019'da eklendi)
Java 8 bunu lambda ile güzel bir şekilde çözer (Guava ve Apache Commons hala daha fazla esneklik sunabilir):
Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
.thenComparing(Report::getStudentNumber)
.thenComparing(Report::getSchool));
@ Gaoagong'un aşağıdaki cevabı için teşekkürler .
Buradaki avantajlardan biri, alıcıların tembel olarak değerlendirilmesidir (örneğin getSchool()
, sadece ilgili ise değerlendirilir).
Dağınık ve kıvrımlı: Elle sıralama
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);
}
});
Bu, çok fazla yazma, bakım gerektirir ve hataya açıktır. Tek avantajı, alıcıların yalnızca ilgili olduğunda çağrılmasıdır.
Yansıtıcı yol: BeanComparator ile sıralama
ComparatorChain chain = new ComparatorChain(Arrays.asList(
new BeanComparator("size"),
new BeanComparator("nrOfToppings"),
new BeanComparator("name")));
Collections.sort(pizzas, chain);
Açıkçası, bu daha özlüdür, ancak bunun yerine Dizeleri kullanarak alanlara doğrudan başvurunuzu kaybettiğinizde (tür güvenliği yok, otomatik yeniden düzenleme yok) daha da hataya meyillidir. Şimdi bir alan yeniden adlandırılırsa, derleyici bir sorun bildirmez bile. Dahası, bu çözüm yansıma kullandığından, sıralama çok daha yavaştır.
Oraya gitmek: Google Guava'nın Karşılaştırma Zinciri ile Sıralama
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();
}
});
Bu çok daha iyidir, ancak en yaygın kullanım durumu için bazı kazan plakası kodu gerektirir: boş değerlere varsayılan olarak daha az değer verilmelidir. Boş alanlar için, Guava'ya bu durumda ne yapacağına fazladan bir yönerge sağlamalısınız. Belirli bir şey yapmak istiyorsanız bu esnek bir mekanizmadır, ancak genellikle varsayılan durumu (yani 1, a, b, z, null) istersiniz.
Ve aşağıdaki yorumlarda belirtildiği gibi, bu alıcıların tümü her karşılaştırma için hemen değerlendirilir.
Apache Commons ile Sıralama 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();
}
});
Guava'nın ComparisonChain'i gibi, bu kütüphane sınıfı birden çok alanda kolaylıkla sıralama yapar, ancak aynı zamanda boş değerler için varsayılan davranışı da tanımlar (yani, 1, a, b, z, null). Bununla birlikte, kendi Karşılaştırıcınızı sağlamadığınız sürece başka bir şey de belirtemezsiniz.
Yine, aşağıdaki yorumlarda belirtildiği gibi, bu alıcıların tümü her karşılaştırma için hemen değerlendirilir.
Böylece
Sonuçta, lezzet ve esneklik ihtiyacı (Guava's ComparisonChain) ile özlü kod (Apache's CompareToBuilder) söz konusudur.
Bonus yöntemi
Ben güzel bir çözüm bulduğunu birleştirir birden karşılaştırıcılar öncelik sırasına göre CodeReview üzerinde bir de 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));
}
}
Tabii ki Apache Commons Collections bunun için zaten bir kullanıma sahiptir:
ComparatorUtils.chainedComparator (comparatorCollection)
Collections.sort(list, ComparatorUtils.chainedComparator(comparators));