Giới thiệu
Kiểm tra xem một giá trị đã có trong ListView hay chưa trước khi thêm mới. Sử dụng ArrayList.contains() (O(n)) hoặc HashSet (O(1)) để tối ưu. Tránh trùng lặp dữ liệu.
Triển khai
Bước 1: Tạo dự án
Android Studio → New Project → Empty Activity.
Bước 2: 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"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<EditText
android:id="@+id/edit_query"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nhập tên thiết bị (Android, iPhone...)" />
<Button
android:id="@+id/buttonPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Thêm / Kiểm tra" />
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="16dp" />
</LinearLayout>
Bước 3: MainActivity.java
package com.example.myapplication;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
ListView listView;
EditText editQuery;
Button btnCheck;
// Dữ liệu gốc
String[] mobileArray = {"Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X"};
// Dùng ArrayList cho Adapter
ArrayList<String> arrayList;
// Dùng HashSet cho kiểm tra O(1)
Set<String> existingSet;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editQuery = findViewById(R.id.edit_query);
btnCheck = findViewById(R.id.buttonPanel);
listView = findViewById(R.id.list);
// Khởi tạo dữ liệu
arrayList = new ArrayList<>(Arrays.asList(mobileArray));
existingSet = new HashSet<>(arrayList); // Sync với arrayList
// Adapter
adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, arrayList);
listView.setAdapter(adapter);
btnCheck.setOnClickListener(v -> {
String input = editQuery.getText().toString().trim();
if (input.isEmpty()) {
Toast.makeText(this, "Vui lòng nhập giá trị", Toast.LENGTH_SHORT).show();
return;
}
// KIỂM TRA TỒN TẠI - O(1) với HashSet
if (existingSet.contains(input)) {
Toast.makeText(this, "⚠ '" + input + "' đã có trong danh sách", Toast.LENGTH_LONG).show();
} else {
// Thêm mới
arrayList.add(input);
existingSet.add(input); // Đồng bộ set
adapter.notifyDataSetChanged(); // Cập nhật ListView
Toast.makeText(this, "✓ Đã thêm '" + input + "'", Toast.LENGTH_SHORT).show();
editQuery.setText(""); // Clear input
}
});
}
}
So sánh phương pháp kiểm tra
| Phương pháp | Độ phức tạp | Code | Phù hợp |
|---|---|---|---|
| ArrayList.contains() | O(n) | list.contains(item) | List nhỏ (<100), ít thao tác |
| HashSet.contains() | O(1) | set.contains(item) | List lớn, kiểm tra thường xuyên |
| Adapter.getPosition() | O(n) | adapter.getPosition(item) >= 0 | Chỉ khi không có access đến data source |
Pattern đồng bộ List + Set
class SyncedList<T> {
private final List<T> list = new ArrayList<>();
private final Set<T> set = new HashSet<>();
public boolean add(T item) {
if (set.contains(item)) return false;
list.add(item);
set.add(item);
return true;
}
public boolean remove(T item) {
boolean removed = list.remove(item);
if (removed) set.remove(item);
return removed;
}
public List<T> getList() { return list; }
public boolean contains(T item) { return set.contains(item); }
}
Kết quả
- Khởi động: ListView hiển thị 8 thiết bị có sẵn
- Nhập "Android" → Toast "⚠ 'Android' đã có trong danh sách"
- Nhập "Samsung" → Thêm vào cuối list, Toast "✓ Đã thêm 'Samsung'"
Mở rộng: Tìm kiếm real-time (Filter)
editQuery.addTextChangedListener(new TextWatcher() {
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s); // Tự động lọc ListView
}
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void afterTextChanged(Editable s) {}
});
Lưu ý: ArrayAdapter có sẵn Filter cho tìm kiếm đơn giản. Với dữ liệu phức tạp/custom object, cần implement Filterable interface.