Sử dụng Queue trong Java? | How to to use Queue in Java?

Bài viết này tôi sẽ mô tả về Queue, cách nó hoạt động, và cách sử dụng nó trong ngôn ngữ lập trình Java.

Java Queue là gì? - What is Java Queue?

Queue dịch sang ngôn ngữ máy tính tiếng việt có nghĩa là hằng đợi, Trong bài viết này ta sẽ tìm hiểu về Queue trong ngôn ngữ lập trình Java.

Queue là một cấu trúc dữ liệu, dùng để lưu trữ nhiều đối tượng(phần tử dữ liệu) làm việc theo cơ chế "vào trước, ra trước" (First In/First Out (FIFO))

Bạn có thể liên tưởng tới việc lấy cái ống tạm thời che một đầu rồi cho các viên bi theo thứ tự từ 1 tới 10 vào cái ống đó, và nguyên tắc lấy bi ra là phải lấy từ đầu bị bịt kín bên dưới, và khi mở đầu bị bịt kín thì bạn sẽ lấy ra được viên bi số 1 đầu tiên(cũng là viên được cho vào ống đầu tiên).

Liên tưởng trong cuộc sống thì nó là hành động chờ xếp hàng để được phục vụ, thì vụ như khi smartphone IPhone 6 được phát hành thì bạn muốn mua sớm thì phải xếp hàng 2-3 ngày gì đó, và nếu bạn xếp háng trước thì sẽ được mua hàng trước.



Các lệnh cơ bản của Queue. - The basic command of the Queue.
  • Push: thêm 1 phần tử vào đỉnh Queue
  • Pop: lấy 1 phần tử từ đỉnh Queue
  • Peek: trả về phần tử đầu Queue mà không loại bỏ nó ra khỏi Queue
  • isEmpty: Kiểm tra Queue có rỗng ko?


Ví dụ đơn giản các lệnh của Queue. - Example basic command of Queue.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package z.test;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

/**
 *
 * @author bnson
 */
public class QueueExample {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Queue<Integer> qe = new LinkedList<Integer>();
       
       
        //Thêm một phần tử vào Queue.
        //Vòng lập for mô tả hoạt động đầu vào của Queue.      
        System.out.println("-- Vào trước/First in --");
        for (int i = 1; i < 10; i++) {
            System.out.println("Postion " + i + ": " + i);
            qe.add(i);
        }

        //Khi ta sử dụng lệnh POP để remove giá trị đầu tiên,
        //ta thấy giá trị 1 vào đầu tiên sẽ được xử lý trước tiên.
        //Đoạn mã bên dưới ngoài việc mô tả hoạt đông vào sau ra trước của Queue,
        //Còn xử lý loại bỏ tất cả các phần tử trong Queue khiến nó trở thành mảng rỗng.
        System.out.println("");
        System.out.println("-- Ra trước/First Out --");       
        while (!qe.isEmpty()) {
            System.out.println("Poll: " + qe.poll());           
        }
       
        //Kiểm tra Queue có rỗng không? | Check Queue is empty?
        System.out.println("");
        System.out.println("-- Queue is empty: " + qe.isEmpty());           
       
        //Do Queue đã là rỗng nên ta sẽ add lại giá trị cho nó,
        //để hướng dẫn các câu lệnh tiếp theo.
        System.out.println("");
        System.out.println("-- Thêm lại giá trị vào Queue. --");
        for (int i = 1; i < 10; i++) {
            System.out.println("Postion " + i + ": " + i);
            qe.offer(i);
        }
       
        //Khác với Stack, Queue không hỗ trợ phương thức Search,
        //vì vậy khi muốn duyệt mảng mà không bị mất giá trị trong Queue,
        //ta phải sử dụng lớp(class) Iterator hỗ trợ.
        System.out.println("");
        System.out.println("-- In các giá trị trong Queue. --");       
        Iterator it=qe.iterator();
        while(it.hasNext())
        {
            int iteratorValue = (Integer)it.next();
            System.out.println("Queue Next Value: " + iteratorValue);
        }       
       
        //Sử dụng lện PEEK trả về phần tử đầu tiên của Queue, nhưng không loại bỏ nó ra khỏi Queue.
        //Tuy nhiên có một nhược điểm là không thể sử dụng nó để xem được giá trị của các phần tử khác,
        //vì nó luôn luôn trả về mỗi giá trị đầu tiên của Queue.
        System.out.println("");
        System.out.println("-- Peek: " + qe.peek());
               
       
        System.out.println("");
        System.out.println("");
        System.out.println(" -- VNLIVES.NET -- ");
       
    }
}


Result - Kết quả.

-- Vào trước/First in --
Postion 1: 1
Postion 2: 2
Postion 3: 3
Postion 4: 4
Postion 5: 5
Postion 6: 6
Postion 7: 7
Postion 8: 8
Postion 9: 9

-- Ra trước/First Out --
Poll: 1
Poll: 2
Poll: 3
Poll: 4
Poll: 5
Poll: 6
Poll: 7
Poll: 8
Poll: 9

-- Queue is empty: true

-- Thêm lại giá trị vào Queue. --
Postion 1: 1
Postion 2: 2
Postion 3: 3
Postion 4: 4
Postion 5: 5
Postion 6: 6
Postion 7: 7
Postion 8: 8
Postion 9: 9

-- In các giá trị trong Queue. --
Queue Next Value: 1
Queue Next Value: 2
Queue Next Value: 3
Queue Next Value: 4
Queue Next Value: 5
Queue Next Value: 6
Queue Next Value: 7
Queue Next Value: 8
Queue Next Value: 9

-- Peek: 1


 -- VNLIVES.NET --


Note - Lưu ý.

Bài này tôi cố viết giống với bài viết Stack trong bài trước, để cho thấy rằng Stack và Queue tương đối nhau, khác biệt rõ ràng nhất là cơ chế làm việc của chúng, Stack là "vào sau, ra trước" (Last In/First Out (LIFO)), Queue là "vào trước, ra trước" (First In/First Out (FIFO)).

Tuy nhiên Queue không hỗ trợ lên search, nên khi bạn muốn tìm kiếm một giá trị trong Queue thì bạn phải duyệt qua tất cả phần tử trong Queue và so sánh với giá trị cần tìm kiếm, để thực được việc này bạn cần phải sử dụng lớp Iterator, tôi sẽ hướng dẫn việc tìm giá trị trong Queue trong các bài viết sau.



Writer: +Bui Ngoc Son





2 comments:

  1. nếu mình viết một lớp các phương thức riêng của Queue cho Array và LinkedList, để hiện thực lại tất cả các phương thức enqueue, dequeue, clear, isEmpty, isFull,... rồi tạo 1 lớp khác viết main. Trường hợp dequeue nhiều hơn số lần enqueue sẽ xảy ra lỗi, vậy làm thế nào để khắc phục? ( không được in ra null)

    ReplyDelete
    Replies
    1. Mình chưa xác định lắm vấn đề của bạn gặp phải, nên mình tạm phán đoán như sau:

      Theo mình thì khi DeQueue(): lấy đối tượng ở đầu queue ra khỏi hàng đợi và trả về giá trị của nó, nếu hàng đợi rỗng thì lỗi sẽ xảy ra, vì vậy theo lý thuyết chương trình của bạn báo lỗi là đúng.

      Để khắc phục tình trạng đây khi bạn cần đồng bộ dequeue(đầu ra) và enqueue(đầu ra) là bằng nhau, vì trên lý thuyến của queue, bạn cho vào bao nhiêu thì chỉ có thể lấy ra bấy nhiêu, không thể cho vào 10 mà lấy ra là 11 được.

      Nếu có gì sai thì bạn update thêm thông tin hoặc source code để chúng ta cùng thảo luận ^^!

      Delete