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

วิธีใช้ Collections.rotate() สำหรับ ListView บน Android

การหมุนลำดับข้อมูลใน ListView ด้วย Collections.rotate()

ตัวอย่างนี้สาธิตการใช้ Collections.rotate() เพื่อเลื่อนตำแหน่งข้อมูลใน ArrayList แบบวนซ้ำ (Circular shift) ก่อนแสดงใน ListView

ขั้นตอนที่ 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 (แก้ไข Logic ให้ถูกต้อง)

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<>();
    private static final int ROTATE_DISTANCE = 2; // เลื่อน 2 ตำแหน่ง

    @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);

                // จุดสำคัญ: ใช้ Collections.rotate() เลื่อนตำแหน่ง
                // distance > 0: เลื่อนไปขวา (ท้ายไปหน้า)
                // distance < 0: เลื่อนไปซ้าย (หน้าไปท้าย)
                if (!arrayList.isEmpty()) {
                    Collections.rotate(arrayList, ROTATE_DISTANCE);
                }

                adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arrayList);
                listView.setAdapter(adapter);

                Toast.makeText(this, "บันทึกสำเร็จ (หมุน " + ROTATE_DISTANCE + " ตำแหน่ง)", Toast.LENGTH_SHORT).show();
            } else {
                etName.setError("กรุณาป้อนชื่อ");
            }
        });
    }
}

คำอธิบาย Collections.rotate()

Collections.rotate(list, distance);
  • เลื่อนองค์ประกอบใน List แบบ Circular (วนกลับมาที่อีกด้าน)
  • distance > 0: เลื่อนไปขวา (Right rotate) - องค์ประกอบท้ายไปอยู่หน้า
  • distance < 0: เลื่อนไปซ้าย (Left rotate) - องค์ประกอบหน้าไปอยู่ท้าย
  • distance = 0 หรือ distance % size == 0: ไม่เปลี่ยนแปลง
  • Time Complexity: O(n) | Space: O(1) - in-place algorithm
  • ทำงานได้กับ List ใดๆ ที่ implements List interface และรองรับ RandomAccess

ตัวอย่างการทำงาน (ROTATE_DISTANCE = 2)

ข้อมูลใน Set: {"A", "B", "C", "D", "E"} → ArrayList (ก่อน rotate): [A, B, C, D, E]

การกระทำArrayList ก่อน rotateหลัง rotate(2) - ขวา 2หลัง rotate(-1) - ซ้าย 1
เพิ่ม A[A][A][A]
เพิ่ม B[A, B][A, B][B, A]
เพิ่ม C[A, B, C][B, C, A][B, C, A]
เพิ่ม D[A, B, C, D][C, D, A, B][B, C, D, A]
เพิ่ม E[A, B, C, D, E][D, E, A, B, C][B, C, D, E, A]

การคำนวณ Rotate (Right rotate 2)

Index เดิม:    0   1   2   3   4
Value:         A   B   C   D   E
                ↓   ↓   ↓   ↓   ↓  (เลื่อนขวา 2)
Index ใหม่:    2   3   4   0   1
Value:         A   B   C   D   E
                ↓
ผลลัพธ์:       D   E   A   B   C
Index:         0   1   2   3   4

กรณีการใช้งานจริง

  • Circular Buffer / Ring Buffer - จัดการ buffer ขนาดคงที่
  • Load Balancing - สลับ Server/Worker แบบ Round-robin
  • Game Development - หมุนตำแหน่งผู้เล่น, หมุนการ์ด
  • Animation - เลื่อนรายการใน Carousel/Marquee
  • Scheduling - Round-robin task scheduling
  • Cryptography - Bit rotation (แต่ระดับ bit)

การ Implement เอง (Manual Rotate)

public static <T> void rotateManual(List<T> list, int distance) {
    if (list == null || list.isEmpty()) return;
    int size = list.size();
    distance = distance % size;
    if (distance < 0) distance += size;
    if (distance == 0) return;

    // ใช้ Collections.reverse() 3 ครั้ง (Efficient in-place)
    Collections.reverse(list);
    Collections.reverse(list.subList(0, distance));
    Collections.reverse(list.subList(distance, size));
}

ข้อควรระวัง

  • rotate() แก้ไข List เดิม (mutating) - copy ก่อนหากต้องการเก็บต้นฉบับ
  • ทำงานได้ดีที่สุดกับ RandomAccess List (ArrayList) - LinkedList จะช้ากว่า
  • distance อาจมากกว่า size - ใช้ modulo เพื่อปรับให้อยู่ในช่วง
  • Empty list หรือ size=1 → rotate ไม่มีผล

เปรียบเทียบ Collections Methods สำหรับจัดลำดับ

Methodการกระทำตัวอย่าง [A,B,C,D,E]
sort()เรียงน้อยไปมาก[A,B,C,D,E]
reverse()กลับลำดับ[E,D,C,B,A]
shuffle()สุ่มลำดับ[C,A,E,B,D]
rotate(list, 2)เลื่อนขวา 2[D,E,A,B,C]
rotate(list, -2)เลื่อนซ้าย 2[C,D,E,A,B]