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

วิธีหาค่าซ้ำใน ArrayList และนำไปเก็บในอีก ArrayList หนึ่งใน Android

การค้นหาค่าซ้ำ (Duplicates) ใน ArrayList

บทความนี้สาธิตวิธีการหาค่าที่ซ้ำกันใน ArrayList และนำค่าซ้ำนั้นๆ ไปเก็บใน ArrayList ใหม่ โดยใช้ HashSet ซึ่งมีประสิทธิภาพ O(1) สำหรับการตรวจสอบค่าซ้ำ

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → File → New Project → Empty Activity

ขั้นตอนที่ 2: Layout - activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ค่าที่ซ้ำกันใน ArrayList"
        android:textSize="20sp"
        android:textStyle="bold"
        android:layout_marginTop="24dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="16dp"
        app:layout_constraintTop_toBottomOf="@id/tvTitle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

ขั้นตอนที่ 3: MainActivity.java - ตรรกะหลัก

package com.example.duplicatesdemo;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MainActivity extends AppCompatActivity {

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

        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        // ข้อมูลตัวอย่าง
        List<String> mainList = new ArrayList<>();
        mainList.add("Sai");
        mainList.add("Sai");           // ซ้ำ
        mainList.add("Ram");
        mainList.add("Sai Krishna");
        mainList.add("Sai Ram Krishna");
        mainList.add("tutorialspoint.com");
        mainList.add("tutorialspoint.com"); // ซ้ำ

        // หาค่าซ้ำ
        List<String> duplicates = findDuplicates(mainList);

        // แสดงผล
        DuplicatesAdapter adapter = new DuplicatesAdapter(duplicates);
        recyclerView.setAdapter(adapter);
    }

    /**
     * หาค่าซ้ำใน List และคืนค่าเป็น List ของค่าที่ซ้ำ (ไม่ซ้ำกันในผลลัพธ์)
     */
    private List<String> findDuplicates(List<String> inputList) {
        Set<String> seen = new HashSet<>();
        Set<String> duplicatesSet = new HashSet<>();

        for (String item : inputList) {
            if (!seen.add(item)) {
                // add() คืนค่า false ถ้ามีค่านี้อยู่แล้ว = ซ้ำ
                duplicatesSet.add(item);
            }
        }

        return new ArrayList<>(duplicatesSet);
    }
}

ขั้นตอนที่ 4: Adapter สำหรับ RecyclerView

package com.example.duplicatesdemo;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;

public class DuplicatesAdapter extends RecyclerView.Adapter<DuplicatesAdapter.ViewHolder> {

    private final List<String> items;

    public DuplicatesAdapter(List<String> items) {
        this.items = items;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(android.R.layout.simple_list_item_1, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.textView.setText(items.get(position));
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(android.R.id.text1);
        }
    }
}

วิธีการทำงาน (Algorithm)

  1. สร้าง HashSet<String> seen เพื่อเก็บค่าที่เคยเจอแล้ว
  2. วนลูปผ่านทุกค่าใน List หลัก
  3. ใช้ seen.add(item):
    • คืนค่า true = ค่าใหม่ ยังไม่เคยเจอ → เพิ่มลงใน seen
    • คืนค่า false = ค่าซ้ำ → เพิ่มลงใน duplicatesSet
  4. แปลง duplicatesSet กลับเป็น ArrayList

ความซับซ้อน (Complexity)

  • Time: O(n) - วนลูปเพียงครั้งเดียว
  • Space: O(n) - เก็บค่าใน HashSet

วิธีอื่น: ใช้ Java 8 Stream (API 24+)

List<String> duplicates = mainList.stream()
    .filter(item -> Collections.frequency(mainList, item) > 1)
    .distinct()
    .collect(Collectors.toList());

หมายเหตุ: วิธี Stream อ่านง่ายแต่ช้ากว่า (O(n²)) ไม่แนะนำสำหรับข้อมูลเยอะ

ขยายความสามารถ: นับจำนวนครั้งที่ซ้ำ

Map<String, Integer> countMap = new HashMap<>();
for (String item : mainList) {
    countMap.put(item, countMap.getOrDefault(item, 0) + 1);
}

// แสดงเฉพาะที่ซ้ำ (count > 1)
for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
    if (entry.getValue() > 1) {
        Log.d("Duplicate", entry.getKey() + " ซ้ำ " + entry.getValue() + " ครั้ง");
    }
}

สรุป

การใช้ HashSet เป็นวิธีที่มีประสิทธิภาพที่สุดสำหรับการหาค่าซ้ำใน ArrayList เหมาะสำหรับข้อมูลขนาดใหญ่ และโค้ดสั้น กระชับ อ่านง่าย