Giới thiệu về size() trong CopyOnWriteArraySet
size() trả về số phần tử trong Set. Với CopyOnWriteArraySet, size() là O(1) vì nội bộ dùng mảng và biến count.
CopyOnWriteArraySet là Set thread-safe, không cho phép duplicate, duy trì thứ tự thêm, iterator snapshot.
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 - Set chỉ giữ 1
actionEvent.setText("Set: " + copyOnWriteArraySet + "\nSize: " + copyOnWriteArraySet.size());
actionEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int size = copyOnWriteArraySet.size();
actionEvent.setText("Size: " + size + "\nSet: " + copyOnWriteArraySet);
}
});
}
}
Kết quả
Ban đầu: Size: 4\nSet: [sai, ram, krishna, prasad] (5 add nhưng "ram" duplicate)
Click: Size = 4
Đặc điểm CopyOnWriteArraySet
| Đặc điểm | Mô tả |
|---|---|
| Thread-safe | Copy-on-write (ghi copy mảng mới) |
| Duplicate | Không cho phép (Set semantics) |
| Thứ tự | Insertion order |
| size() | O(1) - đọc biến count |
| contains() | O(n) - linear search mảng |
| add/remove | O(n) - copy mảng mới |
| Iterator | Snapshot - không ConcurrentModificationException |
| Cho phép null | Không |
So sánh size() các Set thread-safe
| Set | size() | contains() | add/remove | Phù hợp |
|---|---|---|---|---|
| CopyOnWriteArraySet | O(1) | O(n) | O(n) copy | Read-heavy, iterator safe |
| ConcurrentHashMap.newKeySet() | O(1) ước lượng | O(1) | O(1) | General concurrent |
| Collections.synchronizedSet(HashSet) | O(1) + lock | O(1) + lock | O(1) + lock | Simple sync |
Khi nào dùng CopyOnWriteArraySet
- Listener/Observer list (ít add/remove, nhiều iterate)
- Cần iterator an toàn tuyệt đối (snapshot)
- Cấu hình shared, ít thay đổi
- KHÔNG dùng cho: high-frequency updates, large sets
Ví dụ thực tế - Event Listeners
CopyOnWriteArraySet<EventListener> listeners = new CopyOnWriteArraySet<>();
// Đăng ký (ít khi xảy ra)
public void addListener(EventListener l) {
listeners.add(l);
}
// Hủy đăng ký
public void removeListener(EventListener l) {
listeners.remove(l);
}
// Notify (thường xuyên, an toàn iterator)
public void fireEvent(Event e) {
for (EventListener listener : listeners) {
// An toàn: listener có thể add/remove trong này
listener.onEvent(e);
}
}
Lưu ý
- size() O(1) nhưng contains/add/remove O(n)
- Mỗi ghi tạo mảng mới -> GC pressure nếu ghi nhiều
- Iterator không phản ánh thay đổi real-time (snapshot)
- Java 8+: có removeIf(Predicate) nhưng vẫn copy array