Queue Java або просто черга це колекція, яка зберігає елементи у визначеному порядку. Крім основних методів колекцій в цьому інтерфейсі додані додаткові методи вставки, перевірки, вилучення елементу.
В даній колекції елементи зазвичай розміщуються в порядку FIFO – перший прийшов, перший пішов. Найкраща аналогія: черга на касі супермаркету. Хто перший підійшов до каси, той перший буде обслуговуватись.
Важливі моменти про Queue Java:
- Інтерфейс java.util.Queue є підтипом інтерфейсу java.util.Collection.
- Queue вставляє елементи в кінець черги та видаляє з початку черги.
- Черга Java представляє впорядкований список елементів.
- Java Queue підтримує всі методи інтерфейсу Collection.
- Найчастішими реалізаціями Queue є LinkedList, ArrayBlockingQueue і PriorityQueue.
- BlockingQueue не приймає null елементи. Якщо ми виконуємо будь-яку операцію, пов’язану з значенням null, вона викидає виключення NullPointerException.
- ConcurrentLinkedQueue — це необмежена потокобезпечна черга на основі зв’язаних вузлів.
- Усі черги підтримують вставлення в хвіст черги та видалення в початок черги, за винятком Deque.
- Deques — це черги, але вони підтримують вставлення та видалення елементів на обох кінцях.
Queue має власні методи отримання, вставки та видалення елементів. Вони створені для додаткового спрощення роботи, щоб повністю імітувати чергу в реальному житті.
Пропоную відразу розглянути приклад класичної черги на основі LinkedList.
Приклад з LinkedList
package ua.com.antitutor.main;
import java.util.*;
public class QueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.add("Serhiy");
queue.add("Olena");
queue.add("Oleksandr");
queue.add("Svitlana");
System.out.println(queue);
String headElement = queue.peek(); //Отримує, але не видаляє голову цієї черги,
// або повертає значення null, якщо ця черга порожня.
System.out.println(headElement);
String headAndRemove = queue.poll(); //Отримує та видаляє голову цієї черги
// або повертає значення null, якщо ця черга порожня.
System.out.println(headAndRemove);
System.out.println(queue);
String headElementFromElementMethod = queue.element();//Отримує, але не видаляє голову цієї черги.
// Цей метод відрізняється від peek лише тим, що він створює виняток, якщо ця черга порожня.
System.out.println(headElementFromElementMethod);
queue.offer("Dmytro");//Вставляє зазначений елемент у цю чергу,
// якщо це можливо зробити негайно, не порушуючи обмеження на ємність.
// При використанні черги з обмеженням місткості краще використовувати цей метод,
// замість add() оскільки метод offer не викидає виключення якщо черга вже повна на відміну від add
System.out.println(queue);
}
}

Колекція PriorityQueue
PriorityQueue – один з класів реалізацій Queue інтерфейсу. Ця черга упорядковує елементи або за їх натуральним порядком за допомогою інтерфейсу Comparable або за допомогою інтерфейсу Comparator, отриманого в конструкторі.
Comparable і Comparator — це інтерфейси, що визначають стратегію порівняння об’єкта з іншими об’єктами того самого типу. Тобто реалізувавши один з цих інтерфейсів ми можемо вказати Java як сортувати обʼєкти. Адже не завжди обʼєкт це ціле число або рядок. Можливо це щось складніше. Наприклад Авто. В такому випадку програмісту потрібно власноруч вказати як сортувати обʼєкти авто. Для цього і потрібні Comparable і Comparator інтерфейси.
package ua.com.antitutor.main;
import java.util.*;
public class QueueExample {
public static void main(String[] args) {
Queue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.add(7);
priorityQueue.add(4);
priorityQueue.add(9);
priorityQueue.add(1);
priorityQueue.offer(80);
System.out.println(priorityQueue);
System.out.println(priorityQueue.poll());
System.out.println(priorityQueue.peek());
System.out.println(priorityQueue);
}
}

Як бачимо, PriorityQueue використала компаратор щоб посортувати елементи в натуральному порядку. Всі інші методи не відрізняються від List і попереднього прикладу.
Колекція ArrayBlockingQueue
Останнім прикладом на сьогодні я хотів би показати ArrayBlockingQueue. Дана реалізація черги стає в нагоді коли треба обмежити вставку елементів.
package ua.com.antitutor.main;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class QueueExample {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(2);//задаємо розмірність на 2 елементи
System.out.println(queue.add(1));//додаємо перший елементи
System.out.println(queue.add(2));//додаємо другий елементи. Наразі черга повна
System.out.println(queue);
System.out.println(queue.offer(3));//пробуємо додати третій елемент через метод offer
System.out.println(queue);//елемент не додався так як черга повна
queue.add(4);//пробуємо додати ще один елемент через метод add
//отримуємо помилку через те що черга повна
}
}

Як видно з прикладу вище, якщо ми задаємо розмірність черги, то вона не дасть додати більше елементів ніж розраховано. Ви можете використовувати цю властивість при необхідності. І таким чином вам не потрібно буде робити перевірки на повноту перед вставкою.
Залишити відповідь