Giới thiệu về CopyOnWriteArrayList
CopyOnWriteArrayList là List thread-safe, cho phép duplicate, duy trì thứ tự thêm. Mọi phép ghi (add, set, remove) tạo bản sao mảng mới.
remove(Object o) xóa LẦN XUẤT HIỆN ĐẦU TIÊN của phần tử. Trả về true nếu xóa thành công.
remove(int index) xóa phần tử tại vị trí index, trả về phần tử bị xóa.
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.CopyOnWriteArrayList;
public class MainActivity extends AppCompatActivity {
CopyOnWriteArrayList<String> copyOnWriteArrayList;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
copyOnWriteArrayList = new CopyOnWriteArrayList<>();
final TextView actionEvent = findViewById(R.id.actionEvent);
copyOnWriteArrayList.add("sai");
copyOnWriteArrayList.add("ram");
copyOnWriteArrayList.add("krishna");
copyOnWriteArrayList.add("prasad");
copyOnWriteArrayList.add("ram"); // Duplicate - List cho phép
actionEvent.setText("" + copyOnWriteArrayList);
actionEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Xóa LẦN XUẤT HIỆN ĐẦU TIÊN của "ram"
boolean removed = copyOnWriteArrayList.remove("ram");
actionEvent.setText("Đã xóa: " + removed + "\n" + copyOnWriteArrayList);
}
});
}
}
Kết quả
Ban đầu: [sai, ram, krishna, prasad, ram]
Sau click remove("ram"): [sai, krishna, prasad, ram] (chỉ xóa "ram" đầu tiên)
Hai overload của remove()
| Phương thức | Hành động | Trả về |
|---|---|---|
remove(Object o) |
Xóa lần xuất hiện đầu tiên của o | boolean |
remove(int index) |
Xóa phần tử tại index | E (phần tử bị xóa) |
Ví dụ remove(int index)
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A"); list.add("B"); list.add("C"); list.add("B");
// Xóa index 1 (phần tử "B" đầu tiên)
String removed = list.remove(1); // Trả về "B"
// Kết quả: [A, C, B]
Xóa tất cả phần tử trùng lặp
// Cách 1: Loop remove(Object)
while (list.remove("ram")) { }
// Cách 2: removeAll (hiệu quả hơn - chỉ copy 1 lần)
list.removeAll(Collections.singleton("ram"));
// Cách 3: Java 8+ removeIf
list.removeIf(s -> s.equals("ram"));
Đặc điểm hiệu năng
- Read (get, iteration): O(1) - rất nhanh, không lock
- Write (add, remove, set): O(n) - copy toàn bộ mảng
- Bộ nhớ: Tạo object mảng mới mỗi lần ghi
- GC pressure: Cao nếu ghi liên tục
So sánh List thread-safe
| Implementation | Read | Write | Iterator | Phù hợp |
|---|---|---|---|---|
| CopyOnWriteArrayList | O(1) no lock | O(n) copy | Snapshot | Read-heavy, iterator safe |
| Collections.synchronizedList | O(1) + lock | O(1) + lock | Fail-fast (cần sync) | General purpose |
| ArrayList + manual sync | O(1) + lock | O(1) + lock | Fail-fast | Custom control |
Khi nào dùng CopyOnWriteArrayList?
- Danh sách observer/listener (ít add/remove, nhiều notify)
- Cấu hình shared, snapshot iteration
- Event bus subscribers
- KHÔNG dùng cho: real-time, high-frequency updates, large lists