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

วิธีแสดงรายการ ListView แบบสุ่มด้วย Collections.shuffle() บน Android

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

ตัวอย่างนี้สาธิตการใช้ Collections.shuffle() เพื่อสลับลำดับข้อมูลใน ArrayList แบบสุ่ม ก่อนแสดงใน 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

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;
    private Set<String> uniqueSet = new HashSet<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        arrayList = new ArrayList<>();
        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.shuffle(arrayList);

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

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

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

Collections.shuffle(arrayList);
  • สลับลำดับองค์ประกอบใน List แบบสุ่ม (Random permutation)
  • ใช้ Fisher-Yates shuffle algorithm (O(n) time, O(1) space)
  • มี 2 overload:
    • shuffle(List<?> list) - ใช้ default Random
    • shuffle(List<?> list, Random rnd) - ใช้ Random instance ที่กำหนด (สำหรับ reproducible results)
  • ทำงาน in-place (แก้ไข List เดิม)

ตัวอย่างการทำงาน

สมมติข้อมูลใน Set: {"A", "B", "C", "D"}

  • ครั้งที่ 1 กดบันทึก: [C, A, D, B]
  • ครั้งที่ 2 กดบันทึก (เพิ่ม E): [E, B, A, D, C]
  • ครั้งที่ 3 กดรีเฟรช: [A, D, C, B, E] (สุ่มใหม่ทุกครั้งที่กดบันทึก)

การใช้ Random seed เพื่อผลลัพธ์ที่ซ้ำได้ (Reproducible)

// ใช้ seed คงที่ เพื่อให้สุ่มได้ลำดับเดิมทุกครั้ง (ดีสำหรับ testing)
Collections.shuffle(arrayList, new Random(42));

เทคนิคเกี่ยวข้อง

1. สุ่มเพียงบางส่วน (Partial Shuffle)

// สุ่มแค่ 3 ตัวแรก
List<String> sublist = arrayList.subList(0, Math.min(3, arrayList.size()));
Collections.shuffle(sublist);

2. สุ่มโดยไม่แก้ไข List เดิม

List<String> shuffled = new ArrayList<>(arrayList);
Collections.shuffle(shuffled);

3. ใช้ Java Stream (API 24+)

List<String> shuffled = arrayList.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toList(),
        list -> { Collections.shuffle(list); return list; }
    ));

4. สุ่มแบบ Weighted (มีน้ำหนัก)

// ต้อง implement เอง หรือใช้ library เช่น Apache Commons Math

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

  • แอปการเรียนรู้ - สุ่มคำศัพท์ทบทวน
  • เกมไพ่/คำถาม - สุ่มคำถามหรือการ์ด
  • Playlist - สุ่มเพลง (Shuffle play)
  • A/B Testing - สุ่มกลุ่มผู้ใช้
  • Load Testing - สุ่มลำดับ request

ข้อควรระวัง

  • shuffle() แก้ไข List เดิม - copy ก่อนหากต้องการเก็บลำดับเดิม
  • Default Random ไม่ควรใช้สำหรับ Cryptography (ใช้ SecureRandom แทน)
  • สำหรับ List ขนาดใหญ่มาก ควรพิจารณา performance
  • HashSet ไม่รักษาลำดับ - arrayList.addAll(set) จะได้ลำดับไม่แน่นอน ก่อน shuffle

เปรียบเทียบ Collections methods

Methodผลลัพธ์Use Case
sort()เรียงน้อยไปมากเรียง A-Z, 0-9
reverse()กลับลำดับLatest first
shuffle()สุ่มลำดับQuiz, Game, Playlist
rotate()เลื่อนตำแหน่งCircular buffer