Giới thiệu về remove() trong CopyOnWriteArraySet
remove(Object o) xóa phần tử chỉ định khỏi Set. Trả về true nếu phần tử tồn tại và bị xóa, false nếu không tìm thấy.
CopyOnWriteArraySet tạo bản sao mảng mới mỗi lần ghi - thread-safe, iterator snapshot, phù hợp read-heavy.
Ví dụ minh họa
Bước 1: Tạo project
Android Studio → File → New Project.
Bước 2: Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:gravity="center"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:id="@+id/actionEvent"
android:textSize="40sp"
android:layout_marginTop="30dp"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
Bước 3: Code (src/MainActivity.java)
package com.example.myapplication;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import java.util.concurrent.CopyOnWriteArraySet;
public class MainActivity extends AppCompatActivity {
CopyOnWriteArraySet<String> copyOnWriteArraySet;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
copyOnWriteArraySet = new CopyOnWriteArraySet<>();
final TextView actionEvent = findViewById(R.id.actionEvent);
copyOnWriteArraySet.add("sai");
copyOnWriteArraySet.add("ram");
copyOnWriteArraySet.add("krishna");
copyOnWriteArraySet.add("prasad");
copyOnWriteArraySet.add("ram"); // Duplicate - chỉ giữ 1
actionEvent.setText("" + copyOnWriteArraySet);
actionEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Xóa "ram" khỏi Set
boolean removed = copyOnWriteArraySet.remove("ram");
actionEvent.setText("Đã xóa: " + removed + "\n" + copyOnWriteArraySet);
}
});
}
}
Kết quả
Ban đầu (Set unique): [sai, ram, krishna, prasad]
Sau click remove("ram"): [sai, krishna, prasad]
Đặc điểm CopyOnWriteArraySet
| Đặc điểm | Mô tả |
|---|---|
| Thread-safe | Copy-on-write (mọi ghi copy mảng mới) |
| Không cho phép duplicate | Set semantics |
| Iterator | Snapshot - không bao giờ ConcurrentModificationException |
| Cho phép null | Không |
| Thứ tự | Thứ tự thêm (insertion order) |
| Phức tạp add/remove | O(n) - copy mảng |
| Phức tạp contains | O(n) - linear search |
So sánh remove() các Collection
| Collection | remove(o) | Thread-safe | Hiệu năng |
|---|---|---|---|
| CopyOnWriteArraySet | O(n) copy array | Copy-on-write | Ghi chậm, đọc nhanh |
| HashSet | O(1) trung bình | Không | Nhanh nhất single-thread |
| ConcurrentHashMap.newKeySet() | O(1) trung bình | Lock-free/CAS | Cân bằng đọc/ghi |
| Collections.synchronizedSet() | O(1) + lock | Synchronized | Lock contention cao |
Iterator an toàn - Điểm mạnh lớn nhất
CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
set.add("A"); set.add("B"); set.add("C");
// Duyệt an toàn - có thể remove trong loop
for (String s : set) {
if (s.equals("B")) {
set.remove("B"); // KHÔNG ném ConcurrentModificationException
}
}
// Iterator thấy snapshot tại thời điểm tạo: [A, B, C]
Khi nào dùng CopyOnWriteArraySet?
- Listener/Observer pattern (đăng ký ít, notify nhiều)
- Cấu hình shared config (ít thay đổi)
- Cần iterator an toàn tuyệt đối
- KHÔNG dùng cho: high-frequency updates, real-time, big data
Lưu ý
- Mỗi remove() tạo mảng mới - tốn GC nếu xóa nhiều
- Dùng
removeAll()cho batch remove hiệu quả hơn - Không có
removeIf()(Java 8+) - cần tự implement