(จากวิธีเรียงลำดับรายการของวัตถุใน Java ขึ้นอยู่กับหลายสาขา )
รหัสการทำงานในส่วนสำคัญนี้
ใช้ Java 8 lambda's (เพิ่ม 10 เมษายน 2019)
Java 8 แก้ปัญหานี้ได้ดีโดยแลมบ์ดา (แม้ว่า Guava และ Apache Commons อาจยังให้ความยืดหยุ่นมากกว่า):
Collections.sort(reportList, Comparator.comparing(Report::getReportKey)
.thenComparing(Report::getStudentNumber)
.thenComparing(Report::getSchool));
ขอขอบคุณที่ @ gaoagong ของคำตอบด้านล่าง
ยุ่งและซับซ้อน: จัดเรียงด้วยมือ
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);
}
});
สิ่งนี้ต้องการการพิมพ์การบำรุงรักษาและข้อผิดพลาดมากมาย
วิธีการไตร่ตรอง: การเรียงลำดับด้วย BeanComparator
ComparatorChain chain = new ComparatorChain(Arrays.asList(
new BeanComparator("size"),
new BeanComparator("nrOfToppings"),
new BeanComparator("name")));
Collections.sort(pizzas, chain);
เห็นได้ชัดว่านี่คือรัดกุม แต่มีข้อผิดพลาดมากขึ้นในขณะที่คุณสูญเสียการอ้างอิงโดยตรงไปยังเขตข้อมูลโดยใช้ Strings แทน (ไม่มี typesafety, refactorings อัตโนมัติ) ตอนนี้ถ้ามีการเปลี่ยนชื่อฟิลด์คอมไพเลอร์จะไม่รายงานปัญหา นอกจากนี้เนื่องจากวิธีนี้ใช้การสะท้อนการเรียงลำดับจึงช้ากว่ามาก
การเดินทาง: การจัดเรียงด้วยการเปรียบเทียบเชนของ 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();
*/
}
});
สิ่งนี้ดีกว่ามาก แต่ต้องใช้รหัสแผ่นบอยเลอร์สำหรับกรณีการใช้งานทั่วไป: ค่า Null ควรจะมีค่าน้อยลงตามค่าเริ่มต้น สำหรับเขตข้อมูลที่ว่างคุณต้องให้คำสั่งพิเศษแก่ Guava ในกรณีนั้น นี่เป็นกลไกที่ยืดหยุ่นหากคุณต้องการทำสิ่งที่เฉพาะเจาะจง แต่บ่อยครั้งที่คุณต้องการตัวพิมพ์เริ่มต้น (เช่น 1, a, b, z, null)
การเรียงลำดับด้วย 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();
}
});
เช่นเดียวกับการเปรียบเทียบของ Guava คลาสไลบรารีนี้จะเรียงลำดับได้อย่างง่ายดายบนหลายฟิลด์ แต่ยังกำหนดพฤติกรรมเริ่มต้นสำหรับค่า Null (เช่น 1, a, b, z, null) อย่างไรก็ตามคุณไม่สามารถระบุสิ่งอื่นใดได้เว้นแต่คุณจะระบุตัวเปรียบเทียบของคุณเอง
ดังนั้น
ในที่สุดมันก็ลงมาถึงรสชาติและความต้องการความยืดหยุ่น (GuChand's ComparChain) เทียบกับรหัสย่อ (Apache's CompareToBuilder)
วิธีโบนัส
ฉันพบโซลูชันที่ดีที่รวมตัวเปรียบเทียบหลายตัวตามลำดับความสำคัญกับ CodeReviewใน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));
}
}
Ofcourse Apache Commons Collections มีประโยชน์สำหรับเรื่องนี้แล้ว:
ComparatorUtils.chainedComparator (comparatorCollection)
Collections.sort(list, ComparatorUtils.chainedComparator(comparators));