การค้นหาค่าซ้ำ (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)
- สร้าง
HashSet<String> seenเพื่อเก็บค่าที่เคยเจอแล้ว - วนลูปผ่านทุกค่าใน List หลัก
- ใช้
seen.add(item):- คืนค่า
true= ค่าใหม่ ยังไม่เคยเจอ → เพิ่มลงใน seen - คืนค่า
false= ค่าซ้ำ → เพิ่มลงใน duplicatesSet
- คืนค่า
- แปลง 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 เหมาะสำหรับข้อมูลขนาดใหญ่ และโค้ดสั้น กระชับ อ่านง่าย