Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีเรียงลำดับ ListView บน Android

การเรียงลำดับข้อมูลใน 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 โดยตรง