Giới thiệu về removeLastOccurrence()
removeLastOccurrence(Object o) xóa lần xuất hiện CUỐI CÙNG của phần tử chỉ định, bắt đầu tìm từ cuối (tail) deque. Trả về true nếu xóa thành công, false nếu không tìm thấy.
Khác với removeFirstOccurrence() tìm từ đầu, phương thức này duyệt ngược từ cuối.
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.ConcurrentLinkedDeque;
public class MainActivity extends AppCompatActivity {
ConcurrentLinkedDeque<String> concurrentLinkedDeque;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
concurrentLinkedDeque = new ConcurrentLinkedDeque<>();
final TextView actionEvent = findViewById(R.id.actionEvent);
concurrentLinkedDeque.add("sai");
concurrentLinkedDeque.add("ram");
concurrentLinkedDeque.add("krishna");
concurrentLinkedDeque.add("prasad");
concurrentLinkedDeque.add("ram"); // "ram" xuất hiện lần 2 (cuối)
actionEvent.setText("" + concurrentLinkedDeque);
actionEvent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Xóa lần xuất hiện CUỐI CÙNG của "ram" (từ cuối)
boolean removed = concurrentLinkedDeque.removeLastOccurrence("ram");
actionEvent.setText("Đã xóa: " + removed + "\n" + concurrentLinkedDeque);
}
});
}
}
Kết quả
Ban đầu: [sai, ram, krishna, prasad, ram]
Sau click removeLastOccurrence("ram"): [sai, ram, krishna, prasad] (đã xóa "ram" cuối cùng ở vị trí 4)
So sánh First vs Last Occurrence
Deque: [A, B, C, B, D]
removeFirstOccurrence("B") → [A, C, B, D] // Xóa B tại index 1
removeLastOccurrence("B") → [A, B, C, D] // Xóa B tại index 3
Bảng so sánh các phương thức xóa trong Deque
| Phương thức | Vị trí xóa | Điều kiện | Trả về |
|---|---|---|---|
removeFirstOccurrence(o) |
Đầu tiên từ head | equals(o) | boolean |
removeLastOccurrence(o) |
Cuối cùng từ tail | equals(o) | boolean |
remove(o) |
Đầu tiên từ head | equals(o) | boolean |
removeFirst() |
Phần tử head | - | E (ném Exception nếu rỗng) |
removeLast() |
Phần tử tail | - | E (ném Exception nếu rỗng) |
pollFirst() |
Phần tử head | - | E hoặc null |
pollLast() |
Phần tử tail | - | E hoặc null |
Đặc điểm ConcurrentLinkedDeque
- Unbounded: Không giới hạn kích thước
- Thread-safe: Lock-free (CAS - Compare And Swap)
- Hiệu năng: Rất tốt cho high-contention
- Iterator: Weakly consistent (snapshot tại thời điểm tạo)
- Không cho phép null
- Không có blocking operations
Khi nào dùng removeLastOccurrence?
- Cần xóa entry mới nhất của một giá trị (LIFO removal)
- Undo/Redo stack - xóa action gần nhất
- Cache eviction - xóa entry cũ nhất theo giá trị
- Môi trường đa luồng không muốn lock
Lưu ý
- Phức tạp O(n) - phải duyệt tìm phần tử
- Thread-safe nhưng không atomic với các operation khác
- Nếu cần atomic check-then-act, cân nhắc synchronized wrapper