Queue ve Deque
Gerçek hayattaki kuyrukları düşün — banka kuyruğu, market kası, yazıcı kuyruğu. İlk gelen ilk işlenir, son gelen en sona eklenir. Java'daki Queue interface'i tam olarak bu mantığı modelliyor: FIFO (First-In, First-Out).
Deque ise "Double-Ended Queue" — iki uçlu kuyruk. Hem baştan hem sondan ekleme-çıkarma yapabilirsin. Hem kuyruk (FIFO) hem yığın (LIFO — stack) olarak kullanılabilir. İsviçre çakısı gibi.
Queue Interface
Queue, elemanları işlenmek üzere sıraya koyar. Temel operasyonlar iki grupta gelir:
| İşlem | Exception fırlatır | null/false döner |
|---|---|---|
| Ekle | add(e) | offer(e) |
| Çıkar (ve döndür) | remove() | poll() |
| Bak (çıkarmadan) | element() | peek() |
Queue<String> queue = new LinkedList<>();
// Ekleme
queue.offer("Müşteri 1"); // true
queue.offer("Müşteri 2"); // true
queue.offer("Müşteri 3"); // true
// Bakma (çıkarmadan)
System.out.println(queue.peek()); // "Müşteri 1" — ilk eklenen
System.out.println(queue.size()); // 3 — eleman çıkmadı
// Çıkarma
System.out.println(queue.poll()); // "Müşteri 1" — ilk giren ilk çıktı
System.out.println(queue.poll()); // "Müşteri 2"
System.out.println(queue.poll()); // "Müşteri 3"
System.out.println(queue.poll()); // null — kuyruk boşoffer/poll/peek güvenli versiyonlardır — boş kuyruğa poll() çağırırsan null döner. add/remove/element ise hata fırlatır:
Queue<String> queue = new LinkedList<>();
// Boş kuyrukte fark
queue.poll(); // null — güvenli
queue.peek(); // null — güvenli
queue.remove(); // NoSuchElementException!
queue.element(); // NoSuchElementException!💡 İpucu: Her zaman
offer/poll/peeküçlüsünü tercih et. Exception fırlatan versiyonları sadece "kuyruk boşsa bu bir bug'dır" durumlarında kullan.
Deque Interface
Deque (Double-Ended Queue), hem baştan hem sondan erişim sağlar:
addFirst ← [A] [B] [C] [D] → addLast
removeFirst ← [A] [B] [C] [D] → removeLast
getFirst → [A] [D] ← getLastDeque<String> deque = new ArrayDeque<>();
// Başa ekleme
deque.addFirst("B");
deque.addFirst("A"); // [A, B]
// Sona ekleme
deque.addLast("C");
deque.addLast("D"); // [A, B, C, D]
// Baştan çıkarma
deque.removeFirst(); // "A" → [B, C, D]
// Sondan çıkarma
deque.removeLast(); // "D" → [B, C]
// Başa ve sona bakma
deque.peekFirst(); // "B"
deque.peekLast(); // "C"Deque'nin güvenli ve exception fırlatan method'ları:
| İşlem | Exception fırlatır | null/false döner |
|---|---|---|
| Başa ekle | addFirst(e) | offerFirst(e) |
| Sona ekle | addLast(e) | offerLast(e) |
| Baştan çıkar | removeFirst() | pollFirst() |
| Sondan çıkar | removeLast() | pollLast() |
| Başa bak | getFirst() | peekFirst() |
| Sona bak | getLast() | peekLast() |
LinkedList as Queue
LinkedList hem List hem Queue hem Deque interface'lerini implement eder:
// Queue olarak
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
queue.poll(); // "A"
// Deque olarak
Deque<String> deque = new LinkedList<>();
deque.addFirst("A");
deque.addLast("B");Ama Queue/Deque ihtiyacı için ArrayDeque daha iyi. Neden? Birazdan göreceğiz.
ArrayDeque: Tercih Edilen Implementasyon
ArrayDeque, dairesel dizi (circular array) kullanır. LinkedList'ten neredeyse her senaryoda daha hızlıdır.
// Queue olarak
Deque<Integer> queue = new ArrayDeque<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
System.out.println(queue.poll()); // 1 (FIFO)
System.out.println(queue.poll()); // 2
// Stack olarak (LIFO)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.pop()); // 3 (LIFO — son giren ilk çıktı)
System.out.println(stack.pop()); // 2⚠️ ArrayDeque null kabul etmez.
offer(null)→ NullPointerException. LinkedList null kabul eder ama Queue olarak kullanırken null değerpoll()dönüşüyle karışır.
Neden ArrayDeque > LinkedList (Queue/Deque için)?
| Özellik | ArrayDeque | LinkedList |
|---|---|---|
| Bellek | Daha az (dizi) | Daha çok (node nesneleri) |
| Cache performansı | İyi (ardışık bellek) | Kötü (dağınık bellek) |
| null desteği | ❌ | ✅ |
| Hem Queue hem List | ❌ (sadece Deque) | ✅ |
// Modern Java'da kuyruk ihtiyacı → ArrayDeque
Deque<String> queue = new ArrayDeque<>();
// Stack ihtiyacı → ArrayDeque (Stack sınıfını KULLANMA)
Deque<String> stack = new ArrayDeque<>();Deque as Stack
Java'da eski Stack sınıfı var ama kullanma. Synchronized ve Vector tabanlı — yavaş. Deque kullan:
| Stack operasyonu | Deque karşılığı |
|---|---|
push(e) | addFirst(e) veya push(e) |
pop() | removeFirst() veya pop() |
peek() | peekFirst() veya peek() |
// Stack gibi kullanım — LIFO
Deque<String> stack = new ArrayDeque<>();
stack.push("Birinci"); // [Birinci]
stack.push("İkinci"); // [İkinci, Birinci]
stack.push("Üçüncü"); // [Üçüncü, İkinci, Birinci]
System.out.println(stack.pop()); // "Üçüncü" — son giren ilk çıktı
System.out.println(stack.pop()); // "İkinci"
System.out.println(stack.peek()); // "Birinci" — çıkarmadan bakGerçek Dünya: İş Kuyruğu
public class TaskQueue {
private final Deque<Runnable> tasks = new ArrayDeque<>();
public void submit(Runnable task) {
tasks.offer(task);
}
public void submitUrgent(Runnable task) {
tasks.offerFirst(task); // Acil iş başa eklenir
}
public void processNext() {
Runnable task = tasks.poll();
if (task != null) {
task.run();
}
}
public int pendingCount() {
return tasks.size();
}
}Gerçek Dünya: Undo Mekanizması
public class TextEditor {
private String content = "";
private final Deque<String> undoStack = new ArrayDeque<>();
private final Deque<String> redoStack = new ArrayDeque<>();
public void type(String text) {
undoStack.push(content); // Mevcut durumu kaydet
redoStack.clear(); // Redo geçmişini temizle
content += text;
}
public void undo() {
if (!undoStack.isEmpty()) {
redoStack.push(content);
content = undoStack.pop();
}
}
public void redo() {
if (!redoStack.isEmpty()) {
undoStack.push(content);
content = redoStack.pop();
}
}
}Gerçek Dünya: BFS (Breadth-First Search)
public static void bfs(Map<String, List<String>> graph, String start) {
Queue<String> queue = new ArrayDeque<>();
Set<String> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
String node = queue.poll();
System.out.println("Ziyaret: " + node);
for (String neighbor : graph.getOrDefault(node, List.of())) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
}Özet
Queue FIFO (ilk giren ilk çıkar) yapısı —
offer/poll/peekgüvenli method'lar,add/remove/elementexception fırlatırDeque çift uçlu kuyruk — hem baştan hem sondan ekleme/çıkarma, hem Queue hem Stack olarak kullanılır
ArrayDeque neredeyse her zaman LinkedList'ten daha iyi performans verir — Queue/Deque ihtiyacı için ilk tercih
Stack sınıfını kullanma — yerine
Deque<E> stack = new ArrayDeque<>()ile push/pop yapArrayDeque null kabul etmez — null lazımsa LinkedList kullan ama genelde null'dan kaçın
Queue: iş kuyruğu, BFS. Stack (Deque): undo/redo, DFS, parantez eşleme gibi senaryolarda kullan
AI Asistan
Sorularını yanıtlamaya hazır