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

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

การเติมค่าเดียวกันทุกตำแหน่งใน ListView ด้วย Collections.fill()

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

                // จุดสำคัญ: ใช้ Collections.fill() แทนที่ทุกตัวด้วยค่า "Sairam"
                // หมายเหตุ: fill() จะทำงานต่อ List ที่มีขนาดคงที่ (fixed size) หรือมีข้อมูลอยู่แล้ว
                // หาก ArrayList ว่างเปล่า fill() จะไม่ทำอะไร (size = 0)
                if (!arrayList.isEmpty()) {
                    Collections.fill(arrayList, "Sairam");
                }

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

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

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

Collections.fill(list, obj);
  • แทนที่ทุกองค์ประกอบใน List ด้วย obj ที่ระบุ
  • ทำงาน in-place (แก้ไข List เดิม)
  • ต้องการ List ที่มี size > 0 - หาก List ว่าง จะไม่ทำอะไร
  • Time Complexity: O(n) | Space: O(1)
  • List ต้องรองรับ set(int index, E element) operation

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

กรณีปกติ (มีข้อมูลอยู่แล้ว)

ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
// list = [A, B, C, D]

Collections.fill(list, "X");
// list = [X, X, X, X] (ขนาดยังคงเป็น 4)

กรณี List ว่าง (No-op)

ArrayList<String> emptyList = new ArrayList<>();
// size = 0

Collections.fill(emptyList, "X");
// emptyList = [] (ยังคงว่าง - ไม่มี error แต่ไม่ทำอะไร)

กรณีต้องการสร้าง List ใหม่ขนาด n เต็มค่าเดียวกัน

// วิธีที่ 1: ใช้ Collections.nCopies (สร้าง List ใหม่)
List<String> filled = Collections.nCopies(5, "Sairam");
// [Sairam, Sairam, Sairam, Sairam, Sairam] - Immutable list

// วิธีที่ 2: ใช้ ArrayList constructor
ArrayList<String> list = new ArrayList<>(Collections.nCopies(5, "Sairam"));
// Mutable ArrayList

// วิธีที่ 3: Java 8+ Stream
List<String> list = Stream.generate(() -> "Sairam").limit(5).collect(Collectors.toList());

ในตัวอย่างโค้ด (Logic Flow)

  1. User ป้อนชื่อ → เพิ่มลง uniqueSet (HashSet - ไม่ซ้ำ)
  2. arrayList.clear() → arrayList.addAll(uniqueSet) → ArrayList มีข้อมูลไม่ซ้ำ
  3. Collections.fill(arrayList, "Sairam") → แทนที่ทุกตัวเป็น "Sairam"
  4. แสดงใน ListView → ทุกแถวจะเป็น "Sairam"

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

  • Reset/Initialize: ตั้งค่าเริ่มต้นให้ ArrayList (เช่น Default values)
  • Clear Data: ล้างข้อมูลเก่า แทนด้วย Placeholder
  • Testing/Mock: สร้างข้อมูลทดสอบจำนวนมากค่าเดียวกัน
  • Game Board: รีเซ็ตกระดานเกม (Tic-tac-toe, Chess board)
  • Buffer Reuse: ใช้ buffer ซ้ำโดย fill ค่าใหม่

ข้อควรระวัง

  • Mutable List เท่านั้น: ไม่ทำงานกับ Collections.unmodifiableList() หรือ Collections.nCopies() (immutable)
  • Empty List = No-op: ต้องมีข้อมูลอย่างน้อย 1 ตัว ถึงจะ fill ได้
  • Reference Equality: ทุกตำแหน่งจะชี้ไป Object เดียวกัน (Same reference)
  • สำหรับ Immutable objects (String, Integer) ไม่เป็นปัญหา แต่ Mutable objects ต้องระวัง

ตัวอย่างปัญหา Reference Sharing

List<StringBuilder> list = new ArrayList<>(Arrays.asList(
    new StringBuilder("A"), new StringBuilder("B"), new StringBuilder("C")
));
Collections.fill(list, new StringBuilder("X"));
// list = [X, X, X] แต่ทั้ง 3 ชี้ StringBuilder ตัวเดียวกัน!
list.get(0).append("Y");
// list = [XY, XY, XY] - เปลี่ยนทั้งหมด!

เปรียบเทียบ Methods สำหรับเติมค่า

Methodสร้าง List ใหม่แก้ไข List เดิมรองรับ Empty ListMutable Result
Collections.fill()ไม่ใช่ ✓ไม่ (No-op)ใช่
Collections.nCopies()ใช่ ✓ไม่ใช่ ✓ไม่ (Immutable)
Arrays.fill()ไม่ (Array)ใช่ (Array)ใช่ ✓ใช่
Stream.generate().limit()ใช่ ✓ไม่ใช่ ✓ใช่

สรุป

Collections.fill() เหมาะสำหรับ การรีเซ็ตค่าใน List ที่มีอยู่แล้ว ขนาดคงที่ หากต้องการสร้าง List ใหม่ขนาดกำหนด ให้ใช้ Collections.nCopies() หรือ Stream API แทน