การเรียงลำดับ Custom Objects ใน ArrayList
เมื่อมี List ของ Object ต้องการเรียงตาม Property เฉพาะ (เช่น เรียงชื่อ A-Z, เรียงอายุ น้อยไปมาก) ใช้ Comparator หรือ Comparable
2 วิธีหลัก
1. Comparable Interface (Natural Ordering) - ใน Class เอง
public class Student implements Comparable {
String name;
int age;
// ... constructor, getters
@Override
public int compareTo(Student other) {
return this.name.compareTo(other.name); // เรียงตามชื่อ A-Z
}
}
// ใช้งาน
List students = new ArrayList<>();
students.sort(null); // ใช้ Natural Ordering (compareTo)
Collections.sort(students); // วิธีเก่า
2. Comparator (Custom Ordering) - แยกนอก Class ⭐ แนะนำ
// Lambda (Java 8+)
list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
// Method Reference
list.sort(Comparator.comparing(Student::getName));
// หลายเงื่อนไข (ThenComparing)
list.sort(Comparator
.comparing(Student::getAge)
.thenComparing(Student::getName));
// Descending
list.sort(Comparator.comparing(Student::getAge).reversed());
ตัวอย่างที่ 1: ใช้ Comparator ใน main
import java.util.*;
class CustomObject {
private String customProperty;
public CustomObject(String property) {
this.customProperty = property;
}
public String getCustomProperty() {
return this.customProperty;
}
}
public class Demo {
public static void print(ArrayList list) {
for (CustomObject obj : list) {
System.out.println(obj.getCustomProperty());
}
}
public static void sort(ArrayList list) {
list.sort((obj1, obj2) ->
obj1.getCustomProperty().compareTo(obj2.getCustomProperty())
);
}
public static void add(ArrayList list) {
list.add(new CustomObject("Java"));
list.add(new CustomObject("Scala"));
list.add(new CustomObject("Python"));
list.add(new CustomObject("Mysql"));
}
public static void main(String[] args) {
System.out.println("Required packages have been imported");
ArrayList inputList = new ArrayList<>();
add(inputList);
System.out.println("The list is defined as ");
print(inputList);
sort(inputList);
System.out.println("\nThe list after sorting values: ");
print(inputList);
}
}
ผลลัพธ์
Required packages have been imported
The list is defined as
Java
Scala
Python
Mysql
The list after sorting values:
Java
Mysql
Python
Scala
ตัวอย่างที่ 2: Inline ใน main (Modern Java)
import java.util.*;
class CustomObject {
private String customProperty;
public CustomObject(String property) { this.customProperty = property; }
public String getCustomProperty() { return this.customProperty; }
}
public class Demo {
public static void main(String[] args) {
System.out.println("Required packages have been imported");
ArrayList inputList = new ArrayList<>();
inputList.add(new CustomObject("Java"));
inputList.add(new CustomObject("Scala"));
inputList.add(new CustomObject("Python"));
inputList.add(new CustomObject("Mysql"));
System.out.println("The list is defined as ");
for (CustomObject obj : inputList) {
System.out.println(obj.getCustomProperty());
}
// Sort ใช้ Comparator.comparing (Clean & Readable)
inputList.sort(Comparator.comparing(CustomObject::getCustomProperty));
System.out.println("\nThe list after sorting values: ");
for (CustomObject obj : inputList) {
System.out.println(obj.getCustomProperty());
}
}
}
Comparator Patterns ที่น่าสนใจ
Null-safe Sorting
// Nulls First
list.sort(Comparator.comparing(CustomObject::getCustomProperty,
Comparator.nullsFirst(String::compareTo)));
// Nulls Last
list.sort(Comparator.comparing(CustomObject::getCustomProperty,
Comparator.nullsLast(String::compareTo)));
หลาย Property (Chaining)
// เรียง Age ASC แล้ว Name ASC
list.sort(Comparator
.comparing(Student::getAge)
.thenComparing(Student::getName));
// เรียง Age DESC แล้ว Name ASC
list.sort(Comparator
.comparing(Student::getAge).reversed()
.thenComparing(Student::getName));
Custom Comparator Class (Reusable)
public class StudentNameComparator implements Comparator {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
// ใช้งาน
list.sort(new StudentNameComparator());
Comparable vs Comparator
| ด้าน | Comparable | Comparator |
|---|---|---|
| Interface | java.lang.Comparable | java.util.Comparator |
| Method | compareTo(T o) | compare(T o1, T o2) |
| ตำแหน่ง | ภายใน Class (this vs other) | Class แยกหรือ Lambda |
| Sorting Orders | 1 วิธี (Natural Order) | หลายวิธีได้ |
| Modification | ต้องแก้ Class | ไม่ต้องแก้ Class |
| ใช้กับ | Core Domain Objects | Third-party Classes, Multiple Orders |
Performance Notes
List.sort()ใช้ TimSort (Hybrid Merge + Insertion Sort) - O(n log n)- Stable Sort - รักษาลำดับเดิมของ Equal Elements
- Comparator.comparing() สร้าง Comparator แบบ Lazy, ประสิทธิภาพดี
- หลีกเลี่ยงการสร้าง Object ใหม่ใน Comparator (GC Pressure)
สรุป
- ใช้ Comparator.comparing() + Lambda/Method Reference (Java 8+)
- รองรับ Chaining:
thenComparing(),reversed(),nullsFirst/Last() - แยก Comparator ออกจาก Domain Class (Separation of Concerns)
- List.sort() ใช้ TimSort Stable O(n log n)
- Implements Comparable เมื่อมี "Natural Order" ชัดเจน