การเรียงลำดับข้อมูลใน ListView บน Android ด้วย Collections.sort()
ตัวอย่างนี้สาธิตวิธีการเรียงลำดับข้อมูลใน ArrayList แบบต่างๆ ก่อนแสดงใน ListView โดยใช้ Collections.sort() และ Comparator
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
สร้างโปรเจกต์ Android ใหม่ใน Android Studio
ขั้นตอนที่ 2: ออกแบบ Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="ป้อนชื่อ" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button android:id="@+id/btnSave" android:text="บันทึก" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<Button android:id="@+id/btnRefresh" android:text="รีเฟรช" android:layout_width="wrap_content" android:layout_height="wrap_content" />
</LinearLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
</ListView>
</LinearLayout>
ขั้นตอนที่ 3: MainActivity.java
package com.example.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
private EditText etName;
private ListView listView;
private ArrayAdapter<String> adapter;
private ArrayList<String> arrayList = new ArrayList<>();
private Set<String> uniqueSet = new HashSet<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = findViewById(R.id.etName);
listView = findViewById(R.id.listView);
findViewById(R.id.btnRefresh).setOnClickListener(v -> {
if (adapter != null) {
adapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
}
});
findViewById(R.id.btnSave).setOnClickListener(v -> {
String input = etName.getText().toString().trim();
if (!input.isEmpty()) {
uniqueSet.add(input);
arrayList.clear();
arrayList.addAll(uniqueSet);
// จุดสำคัญ: เรียงลำดับ A-Z (Natural Order สำหรับ String)
Collections.sort(arrayList);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arrayList);
listView.setAdapter(adapter);
Toast.makeText(this, "บันทึกสำเร็จ (เรียง A-Z)", Toast.LENGTH_SHORT).show();
} else {
etName.setError("กรุณาป้อนชื่อ");
}
});
}
}
คำอธิบาย Collections.sort()
Collections.sort(list); // 1. Natural Order (ต้อง implements Comparable) Collections.sort(list, comparator); // 2. Custom Order (Comparator)
- Natural Order: String เรียง A-Z, a-z (อิง Unicode Code Point), Number เรียงน้อยไปมาก
- In-place: แก้ไข List เดิมโดยตรง
- Stable Sort: คงลำดับเดิมของค่าที่เท่ากัน (Equal elements)
- Algorithm: TimSort (Hybrid Merge/Insertion Sort) - O(n log n)
ตัวอย่างการทำงาน
Input: "Sairam", "A", "abc", "John", "Zara"
Set (Unique): {Sairam, A, abc, John, Zara}
ArrayList (ก่อน sort): [Sairam, A, abc, John, Zara] (ลำดับไม่แน่นอนจาก HashSet)
หลัง Collections.sort(arrayList):
[A, John, Sairam, Zara, abc]
หมายเหตุ: ตัวพิมพ์ใหญ่ (A-Z: 65-90) จะอยู่ก่อนตัวพิมพ์เล็ก (a-z: 97-122) ตาม Unicode
รูปแบบการเรียงลำดับที่ใช้บ่อย
1. เรียง A-Z (Default - Case Sensitive)
Collections.sort(list);
2. เรียง Z-A (Descending)
Collections.sort(list, Collections.reverseOrder()); // หรือ Collections.sort(list, (a, b) -> b.compareTo(a));
3. เรียง Case-Insensitive (A, a, B, b...)
Collections.sort(list, String.CASE_INSENSITIVE_ORDER); // หรือ Collections.sort(list, (a, b) -> a.compareToIgnoreCase(b));
4. เรียงตามความยาวสตริง (สั้นไปยาว)
Collections.sort(list, (a, b) -> Integer.compare(a.length(), b.length()));
5. เรียงตัวเลขที่เป็น String (Numeric Sort)
Collections.sort(list, (a, b) ->
Double.compare(Double.parseDouble(a), Double.parseDouble(b)));
6. เรียง Object แบบกำหนดเอง
// Class Person { String name; int age; }
Collections.sort(people, (p1, p2) -> {
int nameCmp = p1.getName().compareTo(p2.getName());
if (nameCmp != 0) return nameCmp;
return Integer.compare(p1.getAge(), p2.getAge());
});
Java 8+ Lambda & Method References
// Lambda
list.sort((a, b) -> a.compareTo(b));
// Method Reference
list.sort(String::compareTo);
list.sort(String::compareToIgnoreCase);
list.sort(Comparator.naturalOrder());
list.sort(Comparator.reverseOrder());
// Chaining
list.sort(Comparator.comparing(Person::getName)
.thenComparingInt(Person::getAge)
.thenComparing(Person::getCity));
การเรียงใน Database Layer (แนะนำสำหรับข้อมูลมาก)
แทนที่จะดึงข้อมูลมาทั้งหมดค่อยเรียงใน Java ให้ใช้ SQL ORDER BY:
// ใน DatabaseHelper
Cursor cursor = db.rawQuery(
"SELECT * FROM " + TABLE_NAME + " ORDER BY name ASC", null);
// หรือหลายคอลัมน์
Cursor cursor = db.rawQuery(
"SELECT * FROM " + TABLE_NAME + " ORDER BY salary DESC, name ASC", null);
- เร็วกว่า (Database Engine Optimized)
- ประหยัด Memory (ไม่ต้องโหลดทั้งหมด)
- รองรับ Index เพื่อ Performance
การจัดการ Locale (ภาษาไทย/International)
import java.text.Collator;
import java.util.Locale;
Collator thaiCollator = Collator.getInstance(new Locale("th", "TH"));
thaiCollator.setStrength(Collator.TERTIARY); // คำนึงถึง Swara, Tone Marks
Collections.sort(list, thaiCollator::compare);
- Collator เรียงตามกฎภาษา (Thai: ก-ฮ, สระ, วรรณยุกต์)
- Default String.compareTo() เรียงตาม Unicode Code Point (ไม่ถูกต้องสำหรับไทย)
กรณีการใช้งานจริง
- รายชื่อติดต่อ: เรียงตามชื่อ-นามสกุล
- รายการสินค้า: เรียงตามราคา, ชื่อ, หมวดหมู่
- Log/History: เรียงตามวันที่ (ใหม่-เก่า)
- Leaderboard: เรียงตามคะแนน (สูง-ต่ำ)
- File Manager: เรียงตามชื่อ, ขนาด, วันที่, ประเภท
Best Practices
- ใช้
List.sort(Comparator)(Java 8+) แทน Collections.sort() - กำหนด Comparator ชัดเจน - หลีกเลี่ยง Natural Order ที่อาจสับสน (Case Sensitivity)
- จัดการ Null Values:
Comparator.nullsFirst(),nullsLast() - สำหรับข้อมูลมาก ให้เรียงที่ Database Level (ORDER BY)
- ใช้
Collatorสำหรับภาษาที่ไม่ใช่ Latin
สรุป
Collections.sort() เป็นวิธีง่ายและมีประสิทธิภาพสำหรับการเรียงลำดับข้อมูลใน Memory ก่อนแสดงใน ListView สำหรับแอปพลิเคชันจริงที่มีข้อมูลมาก ควรใช้ ORDER BY ใน SQL Query โดยตรง