Di loket pelayanan pelanggan, orang yang datang lebih dulu dilayani lebih dulu — aturan sederhana yang oleh ilmu komputer dinamai FIFO (first-in, first-out). Interface Queue membawa aturan tersebut ke dalam Collections Framework sebagai cabang tersendiri: elemen dimasukkan lewat ekor antrean dan dikeluarkan lewat kepalanya, sehingga urutan keluar selalu sama dengan urutan masuk. Berbeda dari List yang bisa diakses di posisi mana pun, Queue sengaja membatasi pintu aksesnya agar niat “antrean” terlihat jelas di dalam kode. Pada Chapter ini kita bedah kontrak Queue, kenali dua keluarga method-nya yang tampak kembar namun berperilaku berbeda, lalu membuktikan semuanya dengan antrean layanan sungguhan.
Kontrak Antrean FIFO #
Queue mewarisi seluruh kontrak Collection — tetap bisa size, contains, isEmpty, dan diiterasi — kemudian menambahkan operasi khas antrean pada dua titik istimewa: kepala (elemen yang akan keluar berikutnya) dan ekor (tempat penyisipan baru). Pada antrean FIFO murni seperti ArrayDeque yang kita pakai sebagai Queue, penyisipan selalu terjadi di ekor dan pengambilan di kepala; ArrayDeque, LinkedList, dan PriorityQueue adalah tiga implementasi Queue yang paling umum, dengan PriorityQueue sebagai pengecualian aturan FIFO karena mengurutkan keluaran berdasarkan prioritas (Chapter khusus membahasnya).
Satu keputusan desain membuat Queue istimewa: hampir setiap operasi tersedia dalam dua bentuk. Bentuk pertama melempar Exception ketika operasi gagal; bentuk kedua mengembalikan nilai khusus (false atau null) tanpa mengganggu alur program. Tabel berikut merangkum keenam method tersebut:
| Aksi | Bentuk exception | Bentuk nilai khusus |
|---|---|---|
| Menyisipkan elemen | add(e) → IllegalStateException | offer(e) → false |
| Mengambil & menghapus kepala | remove() → NoSuchElementException | poll() → null |
| Melihat kepala tanpa menghapus | element() → NoSuchElementException | peek() → null |
Untuk penyisipan, perbedaan kedua bentuk baru terlihat pada antrean berkapasitas terbatas: add melempar IllegalStateException saat penuh, sedangkan offer cukup mengembalikan false agar pemanggil memutuskan langkah berikutnya. Untuk pengambilan dan pemeriksaan, perbedaan muncul justru saat antrean kosong — dan inilah yang paling sering dijumpai sehari-hari.
Antrean Layanan dalam Praktik #
Program berikut mengelola antrean pelanggan dengan bentuk nilai khusus (offer, poll, peek), termasuk saat antrean menjadi kosong:
import java.util.*;
public class AntreanLayanan {
public static void main(String[] args) {
Queue<String> antrean = new ArrayDeque<>();
antrean.offer("Budi");
antrean.offer("Siti");
antrean.offer("Dewi");
System.out.println("Isi antrean : " + antrean);
// peek() melihat kepala antrean tanpa menghapus.
System.out.println("peek() : " + antrean.peek());
System.out.println("Setelah peek: " + antrean);
// poll() mengambil kepala antrean dan menghapusnya (FIFO).
System.out.println("poll() : " + antrean.poll());
System.out.println("poll() : " + antrean.poll());
System.out.println("Sisa : " + antrean);
// Antrean sudah kosong: bentuk nilai khusus mengembalikan penanda.
System.out.println("poll() lagi : " + antrean.poll());
System.out.println("peek() lagi : " + antrean.peek());
System.out.println("isEmpty() : " + antrean.isEmpty());
}
}Output yang Dihasilkan:
Isi antrean : [Budi, Siti, Dewi]
peek() : Budi
Setelah peek: [Budi, Siti, Dewi]
poll() : Budi
poll() : Siti
Sisa : [Dewi]
poll() lagi : Dewi
peek() lagi : null
isEmpty() : trueMari kita bedah baris-baris pentingnya:
- Baris 6-8 (
offer(...)tiga kali):Budi,Siti,Dewimasuk lewat ekor antrean. Hasil cetakan[Budi, Siti, Dewi]memperlihatkan urutan kepala-ke-ekor yang sama dengan urutan penyisipan. - Baris 11-12 (
peek()): mengembalikanBudi— kepala antrean — tanpa menghapusnya; cetakan berikutnya membuktikan isi antrean masih utuh tiga orang. - Baris 15-17 (
poll()dua kali):pollmengambil kepala dan menghapusnya.Budikeluar lebih dulu, disusulSiti— urutan keluar sama persis dengan urutan masuk, inti kontrak FIFO. - Baris 20-22 (
poll()danpeek()pada antrean kosong):Dewiterakhir keluar, lalu kedua method mengembalikannulldengan tenang. Tidak ada exception, tidak ada program berhenti — cocok untuk loop yang cukup memeriksapoll() != nullatauisEmpty().
Saat Bentuk Exception yang Dibutuhkan #
Lalu kapan bentuk exception lebih tepat? Ketika antrean kosong berarti bug — kondisi yang seharusnya tidak mungkin terjadi dalam alur normal program. Pada kasus demikian, kegagalan keras lebih berguna karena stack trace menunjuk langsung ke baris yang bermasalah. Berkas berikut sengaja memanggil remove() pada antrean kosong:
import java.util.*;
public class AmbilDariKosong {
public static void main(String[] args) {
Queue<String> antrean = new ArrayDeque<>();
System.out.println("Antrean kosong: " + antrean);
// Bentuk exception: remove() pada antrean kosong melempar error.
String kepala = antrean.remove();
System.out.println("Kepala: " + kepala);
}
}JVM menghentikan program dengan exception berikut:
Exception in thread "main" java.util.NoSuchElementExceptionCetak Antrean kosong: [] sempat tampil, lalu antrean.remove() pada baris kesembilan melempar NoSuchElementException sebelum baris cetak Kepala sempat dieksekusi. Perilaku element() serupa — sama-sama membaca kepala antrean, bedanya element() melempar exception saat kosong sedangkan peek() mengembalikan null.
Queue dengan satu kepala dan satu ekor sudah menyelesaikan banyak kasus, tetapi ada situasi yang menuntut lebih: undo/redo yang mendorong dan menarik dari kedua ujung, deck kartu yang bisa diambil dari atas maupun bawah, atau algoritma pencarian yang bekerja dari dua arah. Untuk itu Java menyediakan Deque — perluasan Queue yang membuka kedua ujungnya sekaligus, materi Chapter berikutnya.
Referensi #
- Java API Specification: java.util.Queue
- Java API Specification: java.util.ArrayDeque
- Dev.java: The Java Collections Framework
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
AmbilDariKosong.java
Unduh berkasimport java.util.*;
public class AmbilDariKosong {
public static void main(String[] args) {
Queue<String> antrean = new ArrayDeque<>();
System.out.println("Antrean kosong: " + antrean);
// Bentuk exception: remove() pada antrean kosong melempar error.
String kepala = antrean.remove();
System.out.println("Kepala: " + kepala);
}
}
AntreanLayanan.java
Unduh berkasimport java.util.*;
public class AntreanLayanan {
public static void main(String[] args) {
Queue<String> antrean = new ArrayDeque<>();
antrean.offer("Budi");
antrean.offer("Siti");
antrean.offer("Dewi");
System.out.println("Isi antrean : " + antrean);
// peek() melihat kepala antrean tanpa menghapus.
System.out.println("peek() : " + antrean.peek());
System.out.println("Setelah peek: " + antrean);
// poll() mengambil kepala antrean dan menghapusnya (FIFO).
System.out.println("poll() : " + antrean.poll());
System.out.println("poll() : " + antrean.poll());
System.out.println("Sisa : " + antrean);
// Antrean sudah kosong: bentuk nilai khusus mengembalikan penanda.
System.out.println("poll() lagi : " + antrean.poll());
System.out.println("peek() lagi : " + antrean.peek());
System.out.println("isEmpty() : " + antrean.isEmpty());
}
}