Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng removeFirstOccurrence() trong LinkedBlockingDeque trên Android

Giới thiệu về removeFirstOccurrence()

removeFirstOccurrence(Object o) xóa lần xuất hiện đầu tiên của phần tử chỉ định, bắt đầu tìm từ đầu (head) deque. Trả về true nếu xóa thành công, false nếu không tìm thấy.

LinkedBlockingDeque thread-safe, optional bounded, phù hợp producer-consumer pattern.

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.LinkedBlockingDeque;

public class MainActivity extends AppCompatActivity {
    LinkedBlockingDeque<String> linkedBlockingDeque;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        linkedBlockingDeque = new LinkedBlockingDeque<>();
        final TextView actionEvent = findViewById(R.id.actionEvent);

        linkedBlockingDeque.add("sai");
        linkedBlockingDeque.add("ram");
        linkedBlockingDeque.add("krishna");
        linkedBlockingDeque.add("prasad");
        linkedBlockingDeque.add("ram"); // "ram" xuất hiện lần 2

        actionEvent.setText("" + linkedBlockingDeque);

        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" (từ head)
                boolean removed = linkedBlockingDeque.removeFirstOccurrence("ram");
                actionEvent.setText("Đã xóa: " + removed + "\n" + linkedBlockingDeque);
            }
        });
    }
}

Kết quả

Ban đầu: [sai, ram, krishna, prasad, ram]

Sau click: [sai, krishna, prasad, ram] (đã xóa "ram" đầu tiên ở index 1)

removeFirstOccurrence vs removeLastOccurrence

Deque: [A, B, C, B, D]

removeFirstOccurrence("B") → [A, C, B, D]  // Xóa B đầu tiên (index 1)
removeLastOccurrence("B")  → [A, B, C, D]  // Xóa B cuối cùng (index 3)

Bảng so sánh phương thức xóa

Phương thức Hành động Trả về Không tìm thấy
removeFirstOccurrence(o) Xóa đầu tiên từ head boolean false
removeLastOccurrence(o) Xóa cuối cùng từ tail boolean false
remove(o) Tương đương removeFirstOccurrence boolean false
removeFirst() Xóa head E Exception
removeLast() Xóa tail E Exception

Đặc điểm LinkedBlockingDeque

  • Optional bounded: new LinkedBlockingDeque<>(capacity)
  • Thread-safe: ReentrantLock (2 locks: head/tail)
  • Blocking ops: putFirst, putLast, takeFirst, takeLast
  • Phức tạp removeFirstOccurrence: O(n) - duyệt linked list

Khi nào dùng removeFirstOccurrence?

  • Xóa entry cũ nhất của một giá trị (FIFO removal)
  • Cancel task cụ thể trong queue
  • Deduplication - giữ lại entry mới nhất

Ví dụ thực tế - Cancel Task

LinkedBlockingDeque<Task> taskQueue = new LinkedBlockingDeque<>();

// Thêm tasks
taskQueue.addLast(new Task("Download", "id-1"));
taskQueue.addLast(new Task("Upload", "id-2"));
taskQueue.addLast(new Task("Download", "id-3")); // Duplicate type

// Hủy task "Download" đầu tiên (cũ nhất)
boolean cancelled = taskQueue.removeFirstOccurrence(
    new Task("Download", "id-1") // Cần equals() đúng
);

Lưu ý

  • Dùng equals() để so sánh - override equals/hashCode cho object custom
  • Thread-safe nhưng không atomic với operations khác
  • Phức tạp O(n) - không phù hợp high-frequency removal
  • Có bounded constructor để kiểm soát bộ nhớ