Тестирование и отладка
После реализации протестируйте, чтобы убедиться в правильной работе уникальности.
Запустите проект:
Правой кнопкой на Main.java → Run 'Main.main()'.
В консоли увидите вывод уникальных авторов. Убедитесь, что дубликаты авторов не появляются в списке.
Проверьте уникальность:
Добавьте две книги с одним автором — в Set должно быть только одно имя.
Попробуйте добавить null как автора (если поле author позволяет) — проверьте поведение Set (HashSet позволит один null).
Отладка:
Установите breakpoint в методе addBook перед authors.add() и после — шагайте (F8) и смотрите, меняется ли размер Set.
Если ошибки: NullPointerException (если Set не инициализировано), ArrayIndexOutOfBoundsException (если массив переполнен) — добавьте проверку на размер.
В консоли выводите сообщения, например, если add вернул false: "Автор [name] уже существует".
Эксперименты:
Измените реализацию Set на LinkedHashSet — проверьте, сохраняется ли порядок добавления авторов.
Попробуйте TreeSet — добавьте Comparator, если нужно сортировать авторов по алфавиту (TreeSet требует Comparable для элементов).
Полезные советы для новичков
Инициализация Set: Всегда инициализируйте в конструкторе класса (authors = new HashSet<>();), чтобы избежать NullPointerException.
Проверка возвращаемого значения: Используйте boolean от add/remove для логики (например, уведомление о дубликате).
Custom уникальность: Если уникальность по полю (как author), убедитесь, что equals/hashCode в Book учитывают только author, если нужно (но для Set это не требуется, так как String имеет правильные методы).
Расширение проекта: Подумайте, как добавить метод для проверки, существует ли автор перед добавлением книги (используйте contains).
Производительность: Для малого количества авторов (сотни) любая реализация подойдет; для больших — HashSet fastest.
Практическое задание
Задача 1: Добавьте в Library метод isAuthorUnique(String authorName), который использует contains для проверки, есть ли автор в Set.
Задача 2: В addBook перед добавлением автора проверьте с помощью contains, и если он новый, выведите сообщение "Новый автор добавлен".
Задача 3: Создайте 5-6 книг с 3-4 уникальными авторами (некоторые повторяются), добавьте их, выведите авторов и убедитесь в уникальности.
Реализуйте эти задачи самостоятельно, следуя шагам урока. Это закрепит работу с Set в контексте проекта.
#Java #для_новичков #beginner #Collections #Set
После реализации протестируйте, чтобы убедиться в правильной работе уникальности.
Запустите проект:
Правой кнопкой на Main.java → Run 'Main.main()'.
В консоли увидите вывод уникальных авторов. Убедитесь, что дубликаты авторов не появляются в списке.
Проверьте уникальность:
Добавьте две книги с одним автором — в Set должно быть только одно имя.
Попробуйте добавить null как автора (если поле author позволяет) — проверьте поведение Set (HashSet позволит один null).
Отладка:
Установите breakpoint в методе addBook перед authors.add() и после — шагайте (F8) и смотрите, меняется ли размер Set.
Если ошибки: NullPointerException (если Set не инициализировано), ArrayIndexOutOfBoundsException (если массив переполнен) — добавьте проверку на размер.
В консоли выводите сообщения, например, если add вернул false: "Автор [name] уже существует".
Эксперименты:
Измените реализацию Set на LinkedHashSet — проверьте, сохраняется ли порядок добавления авторов.
Попробуйте TreeSet — добавьте Comparator, если нужно сортировать авторов по алфавиту (TreeSet требует Comparable для элементов).
Полезные советы для новичков
Инициализация Set: Всегда инициализируйте в конструкторе класса (authors = new HashSet<>();), чтобы избежать NullPointerException.
Проверка возвращаемого значения: Используйте boolean от add/remove для логики (например, уведомление о дубликате).
Custom уникальность: Если уникальность по полю (как author), убедитесь, что equals/hashCode в Book учитывают только author, если нужно (но для Set это не требуется, так как String имеет правильные методы).
Расширение проекта: Подумайте, как добавить метод для проверки, существует ли автор перед добавлением книги (используйте contains).
Производительность: Для малого количества авторов (сотни) любая реализация подойдет; для больших — HashSet fastest.
Практическое задание
Задача 1: Добавьте в Library метод isAuthorUnique(String authorName), который использует contains для проверки, есть ли автор в Set.
Задача 2: В addBook перед добавлением автора проверьте с помощью contains, и если он новый, выведите сообщение "Новый автор добавлен".
Задача 3: Создайте 5-6 книг с 3-4 уникальными авторами (некоторые повторяются), добавьте их, выведите авторов и убедитесь в уникальности.
Реализуйте эти задачи самостоятельно, следуя шагам урока. Это закрепит работу с Set в контексте проекта.
#Java #для_новичков #beginner #Collections #Set
👍2
  Раздел 6. Коллекции в Java
Глава 4. Queue и Deque
Интерфейс Queue. Очередь как структура FIFO. Методы offer, poll, peek
Интерфейс Queue<E> — часть Java Collections Framework (JCF) из пакета java.util, предназначенная для хранения элементов, которые обрабатываются в определенном порядке. Queue моделирует очередь, где элементы добавляются в конец (tail) и извлекаются из начала (head). Основной принцип для большинства реализаций — FIFO, хотя есть исключения, например, приоритетные очереди.
Основные характеристики Queue:
FIFO (First-In-First-Out): Элементы обрабатываются в порядке добавления, как очередь в магазине.
Уникальность: Не гарантируется — дубликаты разрешены (зависит от реализации).
Порядок: Определен структурой (обычно порядок добавления или приоритет).
Big O: Зависит от реализации (O(1) для LinkedList, O(log n) для PriorityQueue).
Null элементы: Зависит от реализации (LinkedList позволяет, PriorityQueue — нет).
Где используется:
Очереди задач (например, обработка запросов в сервере).
Буферы (например, поток ввода-вывода).
Алгоритмы (например, обход графа в ширину — BFS).
Queue<E> расширяет Collection<E>, добавляя методы для работы с очередью.
Основные реализации:
LinkedList (как Queue), ArrayDeque и PriorityQueue.
FIFO: Принцип "первым вошел — первым вышел"
FIFO — это структура данных, где:
Элементы добавляются в конец очереди (enqueue).
Элементы извлекаются из начала (dequeue).
Аналогия: Люди в очереди в кассу — первый в очереди обслуживается первым.
Пример FIFO в жизни: Очередь сообщений в чате обрабатывается в порядке отправки.
Нюанс: PriorityQueue нарушает FIFO, сортируя по приоритету (рассмотрим в следующем уроке).
Основные методы Queue: offer, poll, peek
Queue предоставляет методы для работы с очередью, которые отличаются от add/remove Collection тем, как обрабатывают ограничения (например, заполненность).
offer(E e):
Описание: Добавляет элемент в конец очереди.
Возвращаемое значение: true, если добавлен; false, если очередь полная (для bounded очередей, например, с фиксированным размером).
Исключения: NullPointerException, если null в реализациях, не допускающих null (PriorityQueue).
Big O: O(1) для LinkedList/ArrayDeque, O(log n) для PriorityQueue (перестройка кучи).
poll():
Описание: Извлекает и удаляет элемент из начала очереди.
Возвращаемое значение: Элемент (E) или null, если очередь пуста.
Исключения: Нет (безопаснее, чем remove()).
Big O: O(1) для LinkedList/ArrayDeque, O(log n) для PriorityQueue.
peek():
Описание: Возвращает элемент из начала очереди без удаления.
Возвращаемое значение: Элемент (E) или null, если очередь пуста.
Исключения: Нет.
Big O: O(1) для всех реализаций.
Альтернативы (с исключениями):
add(E e): Как offer, но кидает IllegalStateException при переполнении.
remove(): Как poll, но кидает NoSuchElementException, если пусто.
element(): Как peek, но кидает NoSuchElementException, если пусто.
Нюанс: offer/poll/peek предпочтительнее для очередей, так как безопаснее.
#Java #для_новичков #beginner #Collections #Queue
Глава 4. Queue и Deque
Интерфейс Queue. Очередь как структура FIFO. Методы offer, poll, peek
Интерфейс Queue<E> — часть Java Collections Framework (JCF) из пакета java.util, предназначенная для хранения элементов, которые обрабатываются в определенном порядке. Queue моделирует очередь, где элементы добавляются в конец (tail) и извлекаются из начала (head). Основной принцип для большинства реализаций — FIFO, хотя есть исключения, например, приоритетные очереди.
Основные характеристики Queue:
FIFO (First-In-First-Out): Элементы обрабатываются в порядке добавления, как очередь в магазине.
Уникальность: Не гарантируется — дубликаты разрешены (зависит от реализации).
Порядок: Определен структурой (обычно порядок добавления или приоритет).
Big O: Зависит от реализации (O(1) для LinkedList, O(log n) для PriorityQueue).
Null элементы: Зависит от реализации (LinkedList позволяет, PriorityQueue — нет).
Где используется:
Очереди задач (например, обработка запросов в сервере).
Буферы (например, поток ввода-вывода).
Алгоритмы (например, обход графа в ширину — BFS).
Queue<E> расширяет Collection<E>, добавляя методы для работы с очередью.
Основные реализации:
LinkedList (как Queue), ArrayDeque и PriorityQueue.
FIFO: Принцип "первым вошел — первым вышел"
FIFO — это структура данных, где:
Элементы добавляются в конец очереди (enqueue).
Элементы извлекаются из начала (dequeue).
Аналогия: Люди в очереди в кассу — первый в очереди обслуживается первым.
Пример FIFO в жизни: Очередь сообщений в чате обрабатывается в порядке отправки.
Нюанс: PriorityQueue нарушает FIFO, сортируя по приоритету (рассмотрим в следующем уроке).
Основные методы Queue: offer, poll, peek
Queue предоставляет методы для работы с очередью, которые отличаются от add/remove Collection тем, как обрабатывают ограничения (например, заполненность).
offer(E e):
Описание: Добавляет элемент в конец очереди.
Возвращаемое значение: true, если добавлен; false, если очередь полная (для bounded очередей, например, с фиксированным размером).
Исключения: NullPointerException, если null в реализациях, не допускающих null (PriorityQueue).
Big O: O(1) для LinkedList/ArrayDeque, O(log n) для PriorityQueue (перестройка кучи).
poll():
Описание: Извлекает и удаляет элемент из начала очереди.
Возвращаемое значение: Элемент (E) или null, если очередь пуста.
Исключения: Нет (безопаснее, чем remove()).
Big O: O(1) для LinkedList/ArrayDeque, O(log n) для PriorityQueue.
peek():
Описание: Возвращает элемент из начала очереди без удаления.
Возвращаемое значение: Элемент (E) или null, если очередь пуста.
Исключения: Нет.
Big O: O(1) для всех реализаций.
Альтернативы (с исключениями):
add(E e): Как offer, но кидает IllegalStateException при переполнении.
remove(): Как poll, но кидает NoSuchElementException, если пусто.
element(): Как peek, но кидает NoSuchElementException, если пусто.
Нюанс: offer/poll/peek предпочтительнее для очередей, так как безопаснее.
#Java #для_новичков #beginner #Collections #Queue
👍2
  Примеры использования методов
LinkedList как Queue (FIFO):
PriorityQueue (не FIFO, по приоритету):
Все нюансы методов
offer:
Для bounded очередей (с ограничением размера, например, ArrayBlockingQueue) возвращает false, если полная.
Null: LinkedList позволяет, PriorityQueue — NPE.
Custom объекты: Для PriorityQueue должны быть Comparable или нужен Comparator.
poll:
Безопасно для пустой очереди — просто null.
В PriorityQueue извлекает минимальный элемент (или по Comparator).
peek:
Не меняет очередь — только просмотр.
Null при пустой очереди, безопасно.
Ошибки:
NullPointerException: В PriorityQueue при null.
ClassCastException: В PriorityQueue, если элементы не Comparable.
ConcurrentModificationException: При модификации во время итерации (используйте poll вместо Iterator.remove()).
Thread-safety:
LinkedList, PriorityQueue не thread-safe. Используйте BlockingQueue (например, ArrayBlockingQueue) для многопоточности.
Collections.synchronizedCollection() — простой вариант синхронизации.
Производительность:
LinkedList: O(1) для всех методов (двусвязный список).
PriorityQueue: O(log n) для offer/poll (перестройка кучи), O(1) для peek.
ArrayDeque: O(1) для всех (рассмотрим в следующем уроке).
Полезные советы для новичков
Используйте offer/poll/peek: Безопаснее, чем add/remove/element.
LinkedList как Queue: Универсально для FIFO, но больше памяти, чем ArrayDeque.
Custom классы в PriorityQueue: Реализуйте Comparable или передайте Comparator.
Проверка пустоты: queue.isEmpty() перед poll/peek не нужна — null безопасен.
Итерация: For-each для чтения, но не модифицируйте очередь.
#Java #для_новичков #beginner #Collections #Queue
LinkedList как Queue (FIFO):
javaimport java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// Добавление
queue.offer("Задача 1");
queue.offer("Задача 2");
System.out.println(queue); // [Задача 1, Задача 2]
// Просмотр
System.out.println(queue.peek()); // Задача 1 (без удаления)
System.out.println(queue); // [Задача 1, Задача 2]
// Извлечение
String task = queue.poll(); // Задача 1
System.out.println(task); // Задача 1
System.out.println(queue); // [Задача 2]
// Пустая очередь
queue.poll(); // Задача 2
System.out.println(queue.poll()); // null (без исключения)
}
}
Вывод: Показывает FIFO — элементы извлекаются в порядке добавления, null при пустой очереди.
PriorityQueue (не FIFO, по приоритету):
javaimport java.util.PriorityQueue;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<Integer> queue = new PriorityQueue<>();
queue.offer(3);
queue.offer(1);
queue.offer(2);
System.out.println(queue); // [1, 3, 2] — минимальный в начале
System.out.println(queue.peek()); // 1
System.out.println(queue.poll()); // 1
System.out.println(queue); // [2, 3]
}
}
Нюанс: PriorityQueue сортирует по натуральному порядку (или Comparator), не FIFO.
Все нюансы методов
offer:
Для bounded очередей (с ограничением размера, например, ArrayBlockingQueue) возвращает false, если полная.
Null: LinkedList позволяет, PriorityQueue — NPE.
Custom объекты: Для PriorityQueue должны быть Comparable или нужен Comparator.
poll:
Безопасно для пустой очереди — просто null.
В PriorityQueue извлекает минимальный элемент (или по Comparator).
peek:
Не меняет очередь — только просмотр.
Null при пустой очереди, безопасно.
Ошибки:
NullPointerException: В PriorityQueue при null.
ClassCastException: В PriorityQueue, если элементы не Comparable.
ConcurrentModificationException: При модификации во время итерации (используйте poll вместо Iterator.remove()).
Thread-safety:
LinkedList, PriorityQueue не thread-safe. Используйте BlockingQueue (например, ArrayBlockingQueue) для многопоточности.
Collections.synchronizedCollection() — простой вариант синхронизации.
Производительность:
LinkedList: O(1) для всех методов (двусвязный список).
PriorityQueue: O(log n) для offer/poll (перестройка кучи), O(1) для peek.
ArrayDeque: O(1) для всех (рассмотрим в следующем уроке).
Полезные советы для новичков
Используйте offer/poll/peek: Безопаснее, чем add/remove/element.
LinkedList как Queue: Универсально для FIFO, но больше памяти, чем ArrayDeque.
Custom классы в PriorityQueue: Реализуйте Comparable или передайте Comparator.
Проверка пустоты: queue.isEmpty() перед poll/peek не нужна — null безопасен.
Итерация: For-each для чтения, но не модифицируйте очередь.
#Java #для_новичков #beginner #Collections #Queue
👍3
  Раздел 6. Коллекции в Java
Глава 4. Queue и Deque
Реализации: PriorityQueue, LinkedList как очередь. Применение: обработка задач, хранение заявок
Интерфейс Queue<E> имеет несколько реализаций в JCF, каждая оптимизирована под разные сценарии. Сегодня фокус на PriorityQueue и LinkedList (как Queue). Эти реализации демонстрируют разнообразие: от строгого FIFO до приоритетной обработки.
LinkedList<E> как Queue
LinkedList — это двусвязный список (doubly-linked list), который реализует Queue<E> (а также List<E> и Deque<E>). Как очередь, она идеальна для FIFO: добавление в конец, извлечение из начала.
Особенности:
FIFO: Строго соблюдается порядок добавления.
Уникальность: Нет, дубликаты разрешены.
Null: Разрешен (LinkedList позволяет null элементы).
Big O: O(1) для offer (добавление в конец), poll (извлечение из начала), peek (просмотр начала). Contains — O(n), так как перебор списка.
Внутренняя работа: Каждый элемент — узел (node) с ссылками на prev и next. Добавление — создание узла и обновление ссылок. Извлечение — удаление первого узла и сдвиг ссылок.
Нюансы:
Эффективна для частых вставок/удалений в концах (O(1)), но медленная для середины (O(n)).
Память: Выше, чем у ArrayDeque (из-за ссылок на prev/next).
Thread-safety: Нет — для многопоточности используйте BlockingQueue.
Дополнительно: Как Deque, поддерживает добавление/извлечение с обоих концов (об этом в следующем уроке).
Когда использовать: Для простых FIFO-очередей с небольшим размером, или когда нужна универсальность (Queue + List).
Пример кода для LinkedList как Queue:
PriorityQueue<E>
PriorityQueue — это приоритетная очередь на основе кучи (binary heap, min-heap по умолчанию). Она не следует FIFO, а извлекает элементы по приоритету (минимальный первый для натуральных типов).
Особенности:
FIFO: Нет — приоритетный порядок (по Comparable или Comparator).
Уникальность: Нет, дубликаты разрешены.
Null: Не разрешен (NullPointerException).
Big O: O(log n) для offer (вставка в кучу), poll (извлечение минимума с перестройкой), peek — O(1). Contains — O(n), так как перебор.
Внутренняя работа: Хранит элементы в массиве как бинарную кучу. При добавлении/извлечении перестраивает кучу (heapify) для поддержания свойства: родитель <= дети. Приоритет определяется compareTo() или Comparator.
Нюансы:
Порядок итерации: Не гарантирован (куча не sorted list).
Comparator: Передайте при создании: new PriorityQueue<>((a, b) -> b - a) для max-heap.
Размер: Resizable, initial capacity 11.
Thread-safety: Нет — используйте PriorityBlockingQueue для потоков.
Custom объекты: Должны реализовывать Comparable<E> или предоставить Comparator, иначе ClassCastException.
Когда использовать: Для задач с приоритетами (например, планировщик задач, Dijkstra алгоритм).
#Java #для_новичков #beginner #Collections #PriorityQueue #LinkedList
Глава 4. Queue и Deque
Реализации: PriorityQueue, LinkedList как очередь. Применение: обработка задач, хранение заявок
Интерфейс Queue<E> имеет несколько реализаций в JCF, каждая оптимизирована под разные сценарии. Сегодня фокус на PriorityQueue и LinkedList (как Queue). Эти реализации демонстрируют разнообразие: от строгого FIFO до приоритетной обработки.
LinkedList<E> как Queue
LinkedList — это двусвязный список (doubly-linked list), который реализует Queue<E> (а также List<E> и Deque<E>). Как очередь, она идеальна для FIFO: добавление в конец, извлечение из начала.
Особенности:
FIFO: Строго соблюдается порядок добавления.
Уникальность: Нет, дубликаты разрешены.
Null: Разрешен (LinkedList позволяет null элементы).
Big O: O(1) для offer (добавление в конец), poll (извлечение из начала), peek (просмотр начала). Contains — O(n), так как перебор списка.
Внутренняя работа: Каждый элемент — узел (node) с ссылками на prev и next. Добавление — создание узла и обновление ссылок. Извлечение — удаление первого узла и сдвиг ссылок.
Нюансы:
Эффективна для частых вставок/удалений в концах (O(1)), но медленная для середины (O(n)).
Память: Выше, чем у ArrayDeque (из-за ссылок на prev/next).
Thread-safety: Нет — для многопоточности используйте BlockingQueue.
Дополнительно: Как Deque, поддерживает добавление/извлечение с обоих концов (об этом в следующем уроке).
Когда использовать: Для простых FIFO-очередей с небольшим размером, или когда нужна универсальность (Queue + List).
Пример кода для LinkedList как Queue:
javaimport java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.offer("Задача 1"); // Добавление в конец
queue.offer("Задача 2");
queue.offer("Задача 3");
System.out.println(queue); // [Задача 1, Задача 2, Задача 3] — FIFO порядок
System.out.println(queue.peek()); // Задача 1 (просмотр)
System.out.println(queue.poll()); // Задача 1 (извлечение)
System.out.println(queue); // [Задача 2, Задача 3]
queue.offer(null); // Разрешен null
System.out.println(queue.poll()); // Задача 2
}
}
Вывод: Показывает FIFO — элементы извлекаются в порядке добавления, null разрешен.
PriorityQueue<E>
PriorityQueue — это приоритетная очередь на основе кучи (binary heap, min-heap по умолчанию). Она не следует FIFO, а извлекает элементы по приоритету (минимальный первый для натуральных типов).
Особенности:
FIFO: Нет — приоритетный порядок (по Comparable или Comparator).
Уникальность: Нет, дубликаты разрешены.
Null: Не разрешен (NullPointerException).
Big O: O(log n) для offer (вставка в кучу), poll (извлечение минимума с перестройкой), peek — O(1). Contains — O(n), так как перебор.
Внутренняя работа: Хранит элементы в массиве как бинарную кучу. При добавлении/извлечении перестраивает кучу (heapify) для поддержания свойства: родитель <= дети. Приоритет определяется compareTo() или Comparator.
Нюансы:
Порядок итерации: Не гарантирован (куча не sorted list).
Comparator: Передайте при создании: new PriorityQueue<>((a, b) -> b - a) для max-heap.
Размер: Resizable, initial capacity 11.
Thread-safety: Нет — используйте PriorityBlockingQueue для потоков.
Custom объекты: Должны реализовывать Comparable<E> или предоставить Comparator, иначе ClassCastException.
Когда использовать: Для задач с приоритетами (например, планировщик задач, Dijkstra алгоритм).
#Java #для_новичков #beginner #Collections #PriorityQueue #LinkedList
👍2
  Пример кода для PriorityQueue:
Применение очередей: Обработка задач, хранение заявок
Очереди идеальны для сценариев последовательной обработки.
Обработка задач (Task Processing):
Пример: Планировщик задач, где задачи добавляются в очередь и обрабатываются по порядку (FIFO с LinkedList) или по приоритету (PriorityQueue).
Нюанс: В многопоточных системах (например, Thread pool) используйте BlockingQueue для безопасного poll.
Пример кода (простой обработчик):
Хранение заявок (Request Storage):
Пример: Сервер хранит входящие заявки в очередь для последовательной обработки (например, HTTP requests).
С PriorityQueue: Заявки по срочности (high-priority first).
Нюанс: Для реальных систем используйте BlockingQueue (offer/poll с блокировкой при пустой/полной).
Пример кода (приоритетные заявки):
Полезные советы для новичков
LinkedList для простоты: Универсальна для FIFO, легко добавить Deque-функции.
PriorityQueue для приоритетов: Передавайте Comparator для custom порядка (например, max-heap).
Custom классы: Реализуйте Comparable для PriorityQueue, или используйте Comparator.
Пустая очередь: Проверяйте isEmpty() перед poll, или используйте null от poll.
Итерация: For-each для просмотра, но не модифицируйте.
#Java #для_новичков #beginner #Collections #PriorityQueue #LinkedList
javaimport java.util.PriorityQueue;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<Integer> queue = new PriorityQueue<>();
queue.offer(3);
queue.offer(1);
queue.offer(2);
System.out.println(queue); // [1, 3, 2] — min в начале, но итерация не sorted
System.out.println(queue.peek()); // 1 (минимальный)
System.out.println(queue.poll()); // 1
System.out.println(queue); // [2, 3]
// Max-heap с Comparator
Queue<Integer> maxQueue = new PriorityQueue<>((a, b) -> b - a);
maxQueue.offer(3);
maxQueue.offer(1);
maxQueue.offer(2);
System.out.println(maxQueue.poll()); // 3 (максимальный)
// queue.offer(null); // NPE
}
}
Вывод: Элементы извлекаются по приоритету, не по порядку добавления.
Применение очередей: Обработка задач, хранение заявок
Очереди идеальны для сценариев последовательной обработки.
Обработка задач (Task Processing):
Пример: Планировщик задач, где задачи добавляются в очередь и обрабатываются по порядку (FIFO с LinkedList) или по приоритету (PriorityQueue).
Нюанс: В многопоточных системах (например, Thread pool) используйте BlockingQueue для безопасного poll.
Пример кода (простой обработчик):
javaimport java.util.LinkedList;
import java.util.Queue;
public class TaskProcessor {
private Queue<String> tasks = new LinkedList<>();
public void addTask(String task) {
tasks.offer(task);
}
public void processTasks() {
while (!tasks.isEmpty()) {
String task = tasks.poll();
System.out.println("Обработка: " + task);
}
}
}
public class Main {
public static void main(String[] args) {
TaskProcessor processor = new TaskProcessor();
processor.addTask("Задача 1");
processor.addTask("Задача 2");
processor.processTasks(); // Обработка: Задача 1\nОбработка: Задача 2
}
}
Вывод: Задачи обрабатываются FIFO.
Хранение заявок (Request Storage):
Пример: Сервер хранит входящие заявки в очередь для последовательной обработки (например, HTTP requests).
С PriorityQueue: Заявки по срочности (high-priority first).
Нюанс: Для реальных систем используйте BlockingQueue (offer/poll с блокировкой при пустой/полной).
Пример кода (приоритетные заявки):
javaimport java.util.PriorityQueue;
import java.util.Queue;
class Request implements Comparable<Request> {
private String name;
private int priority; // 1 - высокий, 10 - низкий
public Request(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public int compareTo(Request other) {
return Integer.compare(this.priority, other.priority); // Min-heap по приоритету
}
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
Queue<Request> requests = new PriorityQueue<>();
requests.offer(new Request("Заявка A", 5));
requests.offer(new Request("Заявка B", 1)); // Высокий приоритет
requests.offer(new Request("Заявка C", 3));
while (!requests.isEmpty()) {
System.out.println("Обработка: " + requests.poll().getName()); // Заявка B, Заявка C, Заявка A
}
}
}
Вывод: Заявки обрабатываются по приоритету.
Полезные советы для новичков
LinkedList для простоты: Универсальна для FIFO, легко добавить Deque-функции.
PriorityQueue для приоритетов: Передавайте Comparator для custom порядка (например, max-heap).
Custom классы: Реализуйте Comparable для PriorityQueue, или используйте Comparator.
Пустая очередь: Проверяйте isEmpty() перед poll, или используйте null от poll.
Итерация: For-each для просмотра, но не модифицируйте.
#Java #для_новичков #beginner #Collections #PriorityQueue #LinkedList
👍1
  Раздел 6. Коллекции в Java
Глава 4. Queue и Deque
Интерфейс Deque. Двусторонняя очередь (FIFO и LIFO). Реализации: ArrayDeque, LinkedList
Интерфейс Deque<E> — это расширение Queue из пакета java.util, который представляет двустороннюю очередь (double-ended queue). Deque позволяет добавлять, удалять и просматривать элементы как с начала (head), так и с конца (tail) очереди. Это делает Deque универсальной структурой, способной моделировать как обычную очередь (FIFO), так и стек (LIFO), а также комбинированные сценарии.
Ключевые особенности Deque
Двусторонний доступ: Операции с first (начало) и last (конец).
FIFO и LIFO:
FIFO: Добавляйте в конец (addLast), извлекайте из начала (removeFirst) — как стандартная очередь.
LIFO: Добавляйте в начало (addFirst), извлекайте из начала (removeFirst) — как стек.
Уникальность элементов: Не гарантируется — дубликаты разрешены (зависит от реализации).
Null элементы: Зависит от реализации (ArrayDeque позволяет, но не рекомендуется; LinkedList позволяет).
Big O: Зависит от реализации, но обычно O(1) для операций на концах.
Итерация: Поддерживает Iterator для перебора от начала к концу, и descendingIterator() для обратного порядка.
Deque расширяет Queue, добавляя методы для работы с концом. Основные реализации: ArrayDeque (на массиве) и LinkedList (на связном списке). Deque можно использовать как Queue или Stack (вместо устаревшего Stack класса).
Когда использовать Deque:
Для стеков (LIFO, например, undo/redo).
Для очередей с доступом к концу (например, sliding window в алгоритмах).
Для двусторонних операций (например, палиндромы, где проверка с обоих концов).
FIFO и LIFO в Deque: Двусторонняя очередь
Deque поддерживает два основных режима:
FIFO (First-In-First-Out): "Первым вошел — первым вышел".
Добавление: addLast(E e) или offerLast(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Очередь в банке — первый пришел, первый ушел.
LIFO (Last-In-First-Out): "Последним вошел — первым вышел".
Добавление: addFirst(E e) или offerFirst(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Стопка тарелок — последняя сверху первой берется.
Методы Deque (основные, аналогично Queue, но с first/last)
Добавление:
addFirst(E e)/addLast(E e): Добавляет или кидает исключение, если переполнено.
offerFirst(E e)/offerLast(E e): Добавляет, возвращает boolean (false, если переполнено).
Извлечение:
removeFirst()/removeLast(): Извлекает или кидает NoSuchElementException, если пусто.
pollFirst()/pollLast(): Извлекает или возвращает null, если пусто.
Просмотр:
getFirst()/getLast(): Возвращает или кидает NoSuchElementException, если пусто.
peekFirst()/peekLast(): Возвращает или null, если пусто.
Другие: size(), isEmpty(), clear(), iterator(), descendingIterator().
Нюанс: Методы Queue (offer, poll, peek) в Deque эквивалентны offerLast, pollFirst, peekFirst (для FIFO).
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
Глава 4. Queue и Deque
Интерфейс Deque. Двусторонняя очередь (FIFO и LIFO). Реализации: ArrayDeque, LinkedList
Интерфейс Deque<E> — это расширение Queue из пакета java.util, который представляет двустороннюю очередь (double-ended queue). Deque позволяет добавлять, удалять и просматривать элементы как с начала (head), так и с конца (tail) очереди. Это делает Deque универсальной структурой, способной моделировать как обычную очередь (FIFO), так и стек (LIFO), а также комбинированные сценарии.
Ключевые особенности Deque
Двусторонний доступ: Операции с first (начало) и last (конец).
FIFO и LIFO:
FIFO: Добавляйте в конец (addLast), извлекайте из начала (removeFirst) — как стандартная очередь.
LIFO: Добавляйте в начало (addFirst), извлекайте из начала (removeFirst) — как стек.
Уникальность элементов: Не гарантируется — дубликаты разрешены (зависит от реализации).
Null элементы: Зависит от реализации (ArrayDeque позволяет, но не рекомендуется; LinkedList позволяет).
Big O: Зависит от реализации, но обычно O(1) для операций на концах.
Итерация: Поддерживает Iterator для перебора от начала к концу, и descendingIterator() для обратного порядка.
Deque расширяет Queue, добавляя методы для работы с концом. Основные реализации: ArrayDeque (на массиве) и LinkedList (на связном списке). Deque можно использовать как Queue или Stack (вместо устаревшего Stack класса).
Когда использовать Deque:
Для стеков (LIFO, например, undo/redo).
Для очередей с доступом к концу (например, sliding window в алгоритмах).
Для двусторонних операций (например, палиндромы, где проверка с обоих концов).
FIFO и LIFO в Deque: Двусторонняя очередь
Deque поддерживает два основных режима:
FIFO (First-In-First-Out): "Первым вошел — первым вышел".
Добавление: addLast(E e) или offerLast(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Очередь в банке — первый пришел, первый ушел.
LIFO (Last-In-First-Out): "Последним вошел — первым вышел".
Добавление: addFirst(E e) или offerFirst(E e).
Извлечение: removeFirst() или pollFirst().
Просмотр: getFirst() или peekFirst().
Аналогия: Стопка тарелок — последняя сверху первой берется.
Методы Deque (основные, аналогично Queue, но с first/last)
Добавление:
addFirst(E e)/addLast(E e): Добавляет или кидает исключение, если переполнено.
offerFirst(E e)/offerLast(E e): Добавляет, возвращает boolean (false, если переполнено).
Извлечение:
removeFirst()/removeLast(): Извлекает или кидает NoSuchElementException, если пусто.
pollFirst()/pollLast(): Извлекает или возвращает null, если пусто.
Просмотр:
getFirst()/getLast(): Возвращает или кидает NoSuchElementException, если пусто.
peekFirst()/peekLast(): Возвращает или null, если пусто.
Другие: size(), isEmpty(), clear(), iterator(), descendingIterator().
Нюанс: Методы Queue (offer, poll, peek) в Deque эквивалентны offerLast, pollFirst, peekFirst (для FIFO).
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍3
  Реализации Deque: ArrayDeque и LinkedList
ArrayDeque
Описание: ArrayDeque — эффективная реализация Deque на основе кругового массива (circular array), который resizable. Она оптимизирована для операций на концах и рекомендуется как стандартная Deque в Java.
Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) amortized для addFirst/addLast, removeFirst/removeLast, peek (постоянное время). Contains — O(n).
Внутренняя работа: Массив с head и tail индексами. При добавлении/удалении индексы циклически сдвигаются. При заполнении массив удваивается (resizing O(n) rarely).
Нюансы:
Память: Эффективнее LinkedList (нет ссылок на узлы).
Initial capacity: Конструктор с int для начального размера (default 16).
Thread-safety: Нет — используйте для single-thread.
Когда использовать: Для большинства Deque-задач (быстрее LinkedList для концов).
Ограничение: Не реализует List, нет доступа по индексу.
Пример кода для ArrayDeque:
LinkedList
Описание: LinkedList — двусвязный список, который реализует Deque (и Queue, List). Как Deque, она позволяет операции на обоих концах.
Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) для addFirst/addLast, removeFirst/removeLast, peek (ссылки на first/last узлы). Contains — O(n).
Внутренняя работа: Узлы с prev/next ссылками. Добавление — создание узла и обновление ссылок first/last. Удаление — сдвиг ссылок.
Нюансы:
Память: Выше, чем ArrayDeque (каждый узел — объект с ссылками).
Универсальность: Реализует List, так что доступ по индексу (но O(n)).
Thread-safety: Нет.
Когда использовать: Для Deque с дополнительными List-функциями или частых вставок в середину (но для концов ArrayDeque быстрее).
Ограничение: Медленнее ArrayDeque для больших размеров из-за overhead узлов.
Пример кода для LinkedList как Deque (аналогичен ArrayDeque):
Полезные советы для новичков
ArrayDeque по умолчанию: Для большинства Deque-задач — эффективнее.
LinkedList для универсальности: Если нужно List API (get(index)), используйте её.
FIFO vs LIFO: Выбирайте методы (First/Last) по нуждам.
Null: Избегайте, чтобы не путаться.
Итераторы: descendingIterator() для обратного перебора — полезно для LIFO.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
ArrayDeque
Описание: ArrayDeque — эффективная реализация Deque на основе кругового массива (circular array), который resizable. Она оптимизирована для операций на концах и рекомендуется как стандартная Deque в Java.
Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) amortized для addFirst/addLast, removeFirst/removeLast, peek (постоянное время). Contains — O(n).
Внутренняя работа: Массив с head и tail индексами. При добавлении/удалении индексы циклически сдвигаются. При заполнении массив удваивается (resizing O(n) rarely).
Нюансы:
Память: Эффективнее LinkedList (нет ссылок на узлы).
Initial capacity: Конструктор с int для начального размера (default 16).
Thread-safety: Нет — используйте для single-thread.
Когда использовать: Для большинства Deque-задач (быстрее LinkedList для концов).
Ограничение: Не реализует List, нет доступа по индексу.
Пример кода для ArrayDeque:
import java.util.ArrayDeque;
import java.util.Deque;
public class Main {
public static void main(String[] args) {
Deque<String> deque = new ArrayDeque<>();
// FIFO: Очередь
deque.offerLast("Элемент 1"); // Добавление в конец
deque.offerLast("Элемент 2");
System.out.println(deque.pollFirst()); // Элемент 1 (извлечение из начала)
System.out.println(deque.peekFirst()); // Элемент 2 (просмотр)
// LIFO: Стек
deque.offerFirst("Элемент 3"); // Добавление в начало
deque.offerFirst("Элемент 4");
System.out.println(deque.pollFirst()); // Элемент 4 (LIFO)
// Обратный итератор
for (String elem : deque.descendingIterator()) {
System.out.println(elem); // С конца к началу
}
}
}
Вывод: Показывает FIFO и LIFO, операции O(1).
LinkedList
Описание: LinkedList — двусвязный список, который реализует Deque (и Queue, List). Как Deque, она позволяет операции на обоих концах.
Особенности:
FIFO/LIFO: Поддерживает оба.
Уникальность: Нет.
Null: Разрешен.
Big O: O(1) для addFirst/addLast, removeFirst/removeLast, peek (ссылки на first/last узлы). Contains — O(n).
Внутренняя работа: Узлы с prev/next ссылками. Добавление — создание узла и обновление ссылок first/last. Удаление — сдвиг ссылок.
Нюансы:
Память: Выше, чем ArrayDeque (каждый узел — объект с ссылками).
Универсальность: Реализует List, так что доступ по индексу (но O(n)).
Thread-safety: Нет.
Когда использовать: Для Deque с дополнительными List-функциями или частых вставок в середину (но для концов ArrayDeque быстрее).
Ограничение: Медленнее ArrayDeque для больших размеров из-за overhead узлов.
Пример кода для LinkedList как Deque (аналогичен ArrayDeque):
import java.util.LinkedList;
import java.util.Deque;
public class Main {
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
deque.addLast("Элемент 1");
deque.addLast("Элемент 2");
System.out.println(deque.removeFirst()); // Элемент 1
deque.addFirst("Элемент 3");
System.out.println(deque.removeFirst()); // Элемент 3 (LIFO)
}
}
Вывод: То же, что и ArrayDeque, но с List-возможностями.
Полезные советы для новичков
ArrayDeque по умолчанию: Для большинства Deque-задач — эффективнее.
LinkedList для универсальности: Если нужно List API (get(index)), используйте её.
FIFO vs LIFO: Выбирайте методы (First/Last) по нуждам.
Null: Избегайте, чтобы не путаться.
Итераторы: descendingIterator() для обратного перебора — полезно для LIFO.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍2
  Раздел 6. Коллекции в Java
Глава 4. Queue и Deque
Практика:
В «Библиотеке» добавить очередь читателей (Queue<String>) для книги. Когда книга возвращается — выдать её первому из очереди
Откройте проект «Библиотека»
Запустите IntelliJ IDEA и откройте существующий проект LibraryProject. Убедитесь, что классы Book и Library существуют: Book с полями title, author, year (и геттерами), Library с массивом книг, счетчиком bookCount, методом addBook и Set для авторов.
Импортируйте необходимые пакеты:
В файлах, где будете использовать Queue, убедитесь, что импортированы java.util.Queue и java.util.LinkedList (или ArrayDeque — выберите реализацию для FIFO). IDE подскажет, когда вы начнете писать код — используйте Ctrl+Enter для автодобавления импорта.
Выберите реализацию Queue:
Для этого задания используйте LinkedList<String> как Queue — она проста для FIFO и позволяет операции на концах. Альтернатива — ArrayDeque для большей эффективности, если хотите поэкспериментировать.
Обновление класса Book для очереди читателей
Поскольку очередь читателей относится к конкретной книге (кто ждет эту книгу), добавим её в класс Book.
Добавьте поле для Queue<String>:
Откройте файл Book.java.
Объявите приватное поле readerQueue типа Queue<String>, инициализированное как new LinkedList<> (или new ArrayDeque<>).
Это множество будет хранить имена читателей в порядке очереди (FIFO: первый добавленный — первый получит книгу).
Добавьте методы для работы с очередью
Создайте публичный метод addToQueue(String readerName), который:
Добавляет имя читателя в конец очереди с помощью offer (readerQueue.offer(readerName)).
Можно вывести сообщение, например, "Читатель [readerName] добавлен в очередь за книгой [title]".
Создайте публичный метод returnBook(), который моделирует возврат книги:
Проверяет, пуста ли очередь (readerQueue.isEmpty()).
Если пуста — выводит сообщение "Книга свободна, очередь пуста".
Если не пуста — извлекает первого читателя с помощью poll (String nextReader = readerQueue.poll();).
Выводит сообщение "Книга выдана следующему читателю: [nextReader]".
(Опционально: Если книга была занята, здесь можно обновить статус, но для простоты пока опустим).
Обновите конструктор Book:
В конструкторе Book убедитесь, что readerQueue инициализируется (если не сделали при объявлении поля).
Интеграция с классом Library
Теперь обновим Library, чтобы при добавлении книги учитывать очередь, но поскольку очередь в Book, Library будет работать с объектами Book.
Обновите метод addBook(Book book):
В методе addBook оставьте добавление в массив книг, но добавьте проверку: Если очередь читателей в книге не пуста (book.getReaderQueue().isEmpty() == false), выведите сообщение "Книга добавлена, но имеет очередь читателей".
(Это опционально, но поможет связать с практикой).
Добавьте метод для возврата книги
Создайте публичный метод returnBookByTitle(String title), который:
Ищет книгу в массиве по title (перебор с equals).
Если найдена — вызывает returnBook() на объекте Book.
Если не найдена — выводит сообщение "Книга не найдена".
Обновление класса Main для тестирования
Теперь протестируем новую функциональность в Main.
Создайте объекты и добавьте книги:
В методе main создайте объект Library.
Создайте объект Book (например, с title "Война и мир", author "Толстой", year 1869).
Вызовите addBook на Library.
Добавьте читателей в очередь:
Через объект Book вызовите addToQueue несколько раз с разными именами читателей (например, "Иван", "Мария", "Петр").
Вызовите returnBook() на Book — первый читатель ("Иван") должен получить книгу, остальные остаются в очереди.
Протестируйте возврат:
Вызовите returnBook() еще раз — следующий читатель ("Мария") получит.
Продолжите, пока очередь не опустеет — последний вызов вернет null или сообщение о пустоте.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
Глава 4. Queue и Deque
Практика:
В «Библиотеке» добавить очередь читателей (Queue<String>) для книги. Когда книга возвращается — выдать её первому из очереди
Откройте проект «Библиотека»
Запустите IntelliJ IDEA и откройте существующий проект LibraryProject. Убедитесь, что классы Book и Library существуют: Book с полями title, author, year (и геттерами), Library с массивом книг, счетчиком bookCount, методом addBook и Set для авторов.
Импортируйте необходимые пакеты:
В файлах, где будете использовать Queue, убедитесь, что импортированы java.util.Queue и java.util.LinkedList (или ArrayDeque — выберите реализацию для FIFO). IDE подскажет, когда вы начнете писать код — используйте Ctrl+Enter для автодобавления импорта.
Выберите реализацию Queue:
Для этого задания используйте LinkedList<String> как Queue — она проста для FIFO и позволяет операции на концах. Альтернатива — ArrayDeque для большей эффективности, если хотите поэкспериментировать.
Обновление класса Book для очереди читателей
Поскольку очередь читателей относится к конкретной книге (кто ждет эту книгу), добавим её в класс Book.
Добавьте поле для Queue<String>:
Откройте файл Book.java.
Объявите приватное поле readerQueue типа Queue<String>, инициализированное как new LinkedList<> (или new ArrayDeque<>).
Это множество будет хранить имена читателей в порядке очереди (FIFO: первый добавленный — первый получит книгу).
Добавьте методы для работы с очередью
Создайте публичный метод addToQueue(String readerName), который:
Добавляет имя читателя в конец очереди с помощью offer (readerQueue.offer(readerName)).
Можно вывести сообщение, например, "Читатель [readerName] добавлен в очередь за книгой [title]".
Создайте публичный метод returnBook(), который моделирует возврат книги:
Проверяет, пуста ли очередь (readerQueue.isEmpty()).
Если пуста — выводит сообщение "Книга свободна, очередь пуста".
Если не пуста — извлекает первого читателя с помощью poll (String nextReader = readerQueue.poll();).
Выводит сообщение "Книга выдана следующему читателю: [nextReader]".
(Опционально: Если книга была занята, здесь можно обновить статус, но для простоты пока опустим).
Обновите конструктор Book:
В конструкторе Book убедитесь, что readerQueue инициализируется (если не сделали при объявлении поля).
Интеграция с классом Library
Теперь обновим Library, чтобы при добавлении книги учитывать очередь, но поскольку очередь в Book, Library будет работать с объектами Book.
Обновите метод addBook(Book book):
В методе addBook оставьте добавление в массив книг, но добавьте проверку: Если очередь читателей в книге не пуста (book.getReaderQueue().isEmpty() == false), выведите сообщение "Книга добавлена, но имеет очередь читателей".
(Это опционально, но поможет связать с практикой).
Добавьте метод для возврата книги
Создайте публичный метод returnBookByTitle(String title), который:
Ищет книгу в массиве по title (перебор с equals).
Если найдена — вызывает returnBook() на объекте Book.
Если не найдена — выводит сообщение "Книга не найдена".
Обновление класса Main для тестирования
Теперь протестируем новую функциональность в Main.
Создайте объекты и добавьте книги:
В методе main создайте объект Library.
Создайте объект Book (например, с title "Война и мир", author "Толстой", year 1869).
Вызовите addBook на Library.
Добавьте читателей в очередь:
Через объект Book вызовите addToQueue несколько раз с разными именами читателей (например, "Иван", "Мария", "Петр").
Вызовите returnBook() на Book — первый читатель ("Иван") должен получить книгу, остальные остаются в очереди.
Протестируйте возврат:
Вызовите returnBook() еще раз — следующий читатель ("Мария") получит.
Продолжите, пока очередь не опустеет — последний вызов вернет null или сообщение о пустоте.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍2
  Тестирование и отладка
После реализации протестируйте, чтобы убедиться в правильной работе очереди.
Запустите проект:
Правой кнопкой на Main.java → Run 'Main.main()'.
В консоли увидите сообщения о добавлении читателей и выдаче книги по порядку (FIFO: первый добавленный — первый получает).
Проверьте FIFO:
Убедитесь, что читатели выдаются в порядке добавления (offer в конец, poll из начала).
Попробуйте добавить null как читателя — проверьте поведение (LinkedList позволит).
Отладка:
Установите breakpoint в методе returnBook перед poll и после — шагайте (F8) и смотрите размер очереди (readerQueue.size()).
Если ошибки: NullPointerException (если очередь не инициализирована или книга не найдена) — добавьте проверки if (readerQueue != null && !readerQueue.isEmpty()).
ArrayIndexOutOfBoundsException в массиве книг — расширьте массив или используйте динамический список (позже заменим на List).
Эксперименты:
Измените реализацию Queue на ArrayDeque — проверьте, работает ли аналогично (да, но эффективнее по памяти).
Добавьте метод isQueueEmpty() в Book для проверки пустоты — используйте в Library для статистики.
Полезные советы для новичков
Инициализация Queue: Всегда инициализируйте в конструкторе Book (readerQueue = new LinkedList<>();), чтобы избежать NullPointerException.
Проверка возвращаемого: Poll возвращает null при пустой — используйте if (nextReader != null) для сообщений.
Расширение: Подумайте о статусе книги (boolean isAvailable) — при возврате устанавливайте true, при выдаче — false.
Массив книг: Пока используем массив, но заметьте ограничения — в следующих уроках заменим на List<Book>.
Thread-safety: Если проект вырастет, подумайте о ConcurrentLinkedQueue для многопоточности.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
После реализации протестируйте, чтобы убедиться в правильной работе очереди.
Запустите проект:
Правой кнопкой на Main.java → Run 'Main.main()'.
В консоли увидите сообщения о добавлении читателей и выдаче книги по порядку (FIFO: первый добавленный — первый получает).
Проверьте FIFO:
Убедитесь, что читатели выдаются в порядке добавления (offer в конец, poll из начала).
Попробуйте добавить null как читателя — проверьте поведение (LinkedList позволит).
Отладка:
Установите breakpoint в методе returnBook перед poll и после — шагайте (F8) и смотрите размер очереди (readerQueue.size()).
Если ошибки: NullPointerException (если очередь не инициализирована или книга не найдена) — добавьте проверки if (readerQueue != null && !readerQueue.isEmpty()).
ArrayIndexOutOfBoundsException в массиве книг — расширьте массив или используйте динамический список (позже заменим на List).
Эксперименты:
Измените реализацию Queue на ArrayDeque — проверьте, работает ли аналогично (да, но эффективнее по памяти).
Добавьте метод isQueueEmpty() в Book для проверки пустоты — используйте в Library для статистики.
Полезные советы для новичков
Инициализация Queue: Всегда инициализируйте в конструкторе Book (readerQueue = new LinkedList<>();), чтобы избежать NullPointerException.
Проверка возвращаемого: Poll возвращает null при пустой — используйте if (nextReader != null) для сообщений.
Расширение: Подумайте о статусе книги (boolean isAvailable) — при возврате устанавливайте true, при выдаче — false.
Массив книг: Пока используем массив, но заметьте ограничения — в следующих уроках заменим на List<Book>.
Thread-safety: Если проект вырастет, подумайте о ConcurrentLinkedQueue для многопоточности.
#Java #для_новичков #beginner #Collections #Deque #ArrayDeque #LinkedList
👍2
  Раздел 6. Коллекции в Java
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
Глава 5. Map — отображения (словари)
Интерфейс Map<K, V> — это часть Java Collections Framework (JCF) из пакета java.util, который представляет структуру для хранения ассоциативных данных. В отличие от других коллекций, таких как List или Set, которые хранят отдельные элементы, Map хранит пары, где каждый ключ (K) связан с значением (V). Это позволяет быстро находить значение по ключу, как в словаре или телефонной книге.
Основные понятия:
Ключ (Key): Уникальный идентификатор для доступа к значению. Ключи не могут дублироваться — если добавить пару с существующим ключом, значение перезапишется.
Значение (Value): Данные, ассоциированные с ключом. Значения могут дублироваться.
Пара (Entry): Единица хранения в Map — комбинация ключа и значения.
Map моделирует математическое отображение (mapping), где каждый ключ maps to ровно одно значение. Это делает Map идеальным для сценариев, где нужна ассоциация, например, ID пользователя — профиль, слово — перевод.
Отличия от Collection:
Map не расширяет Collection<E> — это отдельная ветвь JCF.
Collection — последовательность элементов, Map — ассоциативный массив.
В Map нет индексации (нет get(int index)), доступ только по ключу.
Размер Map — количество пар, не элементов.
Generics в Map: <K, V> обеспечивает типобезопасность: ключи одного типа (например, Integer), значения другого (String). Без generics (raw Map) — устарело и небезопасно.
Хранение пар «ключ–значение»: Особенности
Map хранит данные в форме пар, где ключ — уникальный, а значение — связанное с ним. Это позволяет эффективно решать задачи поиска и ассоциации.
Уникальность ключей:
Ключи всегда уникальны: Map не позволяет дубликаты ключей. Если ключ уже существует, значение обновляется.
Уникальность определяется методами equals() и hashCode() (в hash-based реализациях) или compareTo() (в sorted).
Нюанс: Для custom ключей обязательно переопределите equals() и hashCode() — иначе уникальность по ссылке, не по значению.
Дубликаты значений:
Значения могут повторяться: Несколько ключей могут ссылаться на одно значение.
Нюанс: Если значение — mutable объект, изменения в одном месте отразятся везде (по ссылке).
Null в Map:
Ключи: Большинство реализаций позволяют один null-ключ (HashMap, LinkedHashMap), но TreeMap — нет (NullPointerException).
Значения: Null разрешен всегда.
Порядок в Map:
В общем случае нет (зависит от реализации): Не полагайтесь на порядок пар.
Нюанс: Map не упорядочен, как List, но некоторые реализации добавляют порядок.
Размер и емкость:
Размер (size()) — количество пар.
Емкость: В hash-based — initial capacity и load factor (например, 0.75 — при заполнении >75% ресайз).
Производительность:
В среднем O(1) для доступа по ключу в hash-based, O(log n) в tree-based.
Нюанс: Зависит от качества hashCode() — плохие хэши приводят к деградации до O(n).
Полезные советы для новичков
Выбор типов K/V: Ключи — immutable (String, Integer), чтобы избежать изменений, влияющих на хэш.
Custom ключи: Переопределяйте equals/hashCode (IDE поможет: Generate → equals() and hashCode()).
Map vs другие коллекции: Используйте Map для ассоциаций, Set для уникальных элементов, List для последовательностей.
#Java #для_новичков #beginner #Map
👍4
  Раздел 6. Коллекции в Java
Глава 5. Map — отображения (словари)
Реализации: HashMap, LinkedHashMap, TreeMap и остальные
JCF предоставляет богатый набор реализаций Map, каждая оптимизирована под конкретные нужды.
Все они реализуют Map<K, V>, но различаются по:
Хранению: Хэш-таблица (HashMap), связный список + хэш (LinkedHashMap), красно-черное дерево (TreeMap).
Порядку: Нет (HashMap), вставки (LinkedHashMap), сортировка по ключам (TreeMap).
Производительности: O(1) для хэш, O(log n) для дерево.
Дополнительно: Специальные для enum, слабых ссылок и т.д.
1. HashMap<K, V>: Основная реализация
Описание: HashMap — сердце Map в Java, основанная на хэш-таблице. Хранит пары в массиве "бакетов" (buckets), где каждый бакет — список узлов (node) с ключом, значением и хэш-кодом.
Внутренняя структура:
Массив Node<K,V>[] table (initial capacity 16, load factor 0.75).
При put: Вычисляет hash = key.hashCode() ^ (hash >>> 16) для равномерности.
Индекс бакета: hash & (table.length - 1).
Коллизия: LinkedList или Tree (с Java 8, если > 8 узлов — дерево для O(log n)).
Ресайз: При >75% заполнения — удваивает размер, перехэширует все элементы.
Big O:
put/get/remove/containsKey: O(1) средний, O(n) worst (плохие хэши).
Итерация: O(capacity).
Особенности:
Порядок: Нет (iteration order не гарантирован).
Null: Один null-ключ, несколько null-значений.
Thread-safe: Нет (ConcurrentModificationException при параллельном доступе).
Initial capacity/load factor: new HashMap<>(16, 0.75f) для оптимизации.
Нюансы и ловушки:
hashCode/equals: Критичны! Плохой hashCode — деградация до O(n). Изменение ключа после put — потеря элемента.
Ресайз: O(n) время, но редко.
Java 8+: Tree nodes для коллизий (>8 узлов).
Remove: Если null-ключ — специальная обработка.
Итерация: entrySet(), keySet(), values() — O(capacity), не size().
Пример кода:
2. LinkedHashMap<K, V>: HashMap с порядком
Описание: Расширение HashMap с двусвязным списком для сохранения порядка вставки (insertion-order) или доступа (access-order для LRU-кэша).
Внутренняя структура: HashMap + Entry с prev/next ссылками. Два режима: INSERTION_ORDER (default) или ACCESS_ORDER (constructor flag).
Big O: O(1) для put/get/remove, как HashMap.
Особенности:
Порядок: Вставки (по умолчанию) или доступа (get/put обновляет позицию).
Null: Да.
Thread-safe: Нет.
Нюансы:
LRU кэш: new LinkedHashMap<>(16, 0.75f, true) — access-order, removeEldestEntry для eviction.
Итерация: В порядке вставки/доступа.
Ресайз: Как HashMap, но сохраняет порядок.
Пример:
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
Глава 5. Map — отображения (словари)
Реализации: HashMap, LinkedHashMap, TreeMap и остальные
JCF предоставляет богатый набор реализаций Map, каждая оптимизирована под конкретные нужды.
Все они реализуют Map<K, V>, но различаются по:
Хранению: Хэш-таблица (HashMap), связный список + хэш (LinkedHashMap), красно-черное дерево (TreeMap).
Порядку: Нет (HashMap), вставки (LinkedHashMap), сортировка по ключам (TreeMap).
Производительности: O(1) для хэш, O(log n) для дерево.
Дополнительно: Специальные для enum, слабых ссылок и т.д.
1. HashMap<K, V>: Основная реализация
Описание: HashMap — сердце Map в Java, основанная на хэш-таблице. Хранит пары в массиве "бакетов" (buckets), где каждый бакет — список узлов (node) с ключом, значением и хэш-кодом.
Внутренняя структура:
Массив Node<K,V>[] table (initial capacity 16, load factor 0.75).
При put: Вычисляет hash = key.hashCode() ^ (hash >>> 16) для равномерности.
Индекс бакета: hash & (table.length - 1).
Коллизия: LinkedList или Tree (с Java 8, если > 8 узлов — дерево для O(log n)).
Ресайз: При >75% заполнения — удваивает размер, перехэширует все элементы.
Big O:
put/get/remove/containsKey: O(1) средний, O(n) worst (плохие хэши).
Итерация: O(capacity).
Особенности:
Порядок: Нет (iteration order не гарантирован).
Null: Один null-ключ, несколько null-значений.
Thread-safe: Нет (ConcurrentModificationException при параллельном доступе).
Initial capacity/load factor: new HashMap<>(16, 0.75f) для оптимизации.
Нюансы и ловушки:
hashCode/equals: Критичны! Плохой hashCode — деградация до O(n). Изменение ключа после put — потеря элемента.
Ресайз: O(n) время, но редко.
Java 8+: Tree nodes для коллизий (>8 узлов).
Remove: Если null-ключ — специальная обработка.
Итерация: entrySet(), keySet(), values() — O(capacity), не size().
Пример кода:
javaimport java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> ages = new HashMap<>();
ages.put("Алексей", 35);
ages.put("Мария", 28);
ages.put("Алексей", 36); // Перезапись
System.out.println(ages.get("Алексей")); // 36
ages.put(null, 0); // Null-ключ
System.out.println(ages.size()); // 3
// Итерация
for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
Когда использовать: 99% случаев — быстрый поиск/кэш (userId -> User).
2. LinkedHashMap<K, V>: HashMap с порядком
Описание: Расширение HashMap с двусвязным списком для сохранения порядка вставки (insertion-order) или доступа (access-order для LRU-кэша).
Внутренняя структура: HashMap + Entry с prev/next ссылками. Два режима: INSERTION_ORDER (default) или ACCESS_ORDER (constructor flag).
Big O: O(1) для put/get/remove, как HashMap.
Особенности:
Порядок: Вставки (по умолчанию) или доступа (get/put обновляет позицию).
Null: Да.
Thread-safe: Нет.
Нюансы:
LRU кэш: new LinkedHashMap<>(16, 0.75f, true) — access-order, removeEldestEntry для eviction.
Итерация: В порядке вставки/доступа.
Ресайз: Как HashMap, но сохраняет порядок.
Пример:
javaimport java.util.LinkedHashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("A", 3); // Обновляет, но порядок сохраняется
for (String key : map.keySet()) {
System.out.println(key); // A, B — порядок вставки
}
// Access-order
Map<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true);
lru.put("A", 1);
lru.get("A"); // "A" перемещается в конец
}
}
Когда использовать: Кэш с порядком (LRU), когда нужен predictable iteration.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
👍1
  3. TreeMap<K, V>: Отсортированная Map
Описание: Реализация SortedMap<K, V> на красно-черном дереве (red-black tree). Ключи всегда отсортированы.
Внутренняя структура: Дерево узлов с left/right/child ссылками, цветом для баланса.
Big O: O(log n) для put/get/remove/containsKey.
Особенности:
Порядок: Сортировка по ключам (Comparable или Comparator).
Null-ключ: Нет (NPE).
Null-значение: Да.
Thread-safe: Нет.
Нюансы:
Comparator: new TreeMap<>(comparator) для custom сортировки.
Дополнительные методы: firstKey(), lastKey(), headMap(K to), tailMap(K from), subMap.
Custom ключи: Comparable<K> или Comparator.
Баланс: Автоматический, O(log n) гарантировано.
Пример:
Остальные реализации: Hashtable, IdentityHashMap, EnumMap, WeakHashMap
Hashtable<K, V> (устаревшая)
Описание: Первая Map в Java (1.0), synchronized версия HashMap.
Особенности: Thread-safe (synchronized методы), нет null, порядок нет.
Big O: O(1).
Нюансы: Медленнее HashMap (locks на каждый метод), legacy — используйте ConcurrentHashMap.
Когда: Только legacy код.
IdentityHashMap<K, V>
Описание: HashMap с == вместо equals/hashCode (по ссылке).
Особенности: Для объектов, где важна идентичность (graph algorithms).
Big O: O(1).
Нюансы: Load factor 0.5, double hash для коллизий.
Когда: Редко, для identity сравнения.
EnumMap<K extends Enum<K>, V>
Описание: Оптимизированная Map для enum ключей (массив вместо хэш).
Особенности: O(1), порядок enum, нет null-ключа.
Нюансы: Ключи — enum, values any.
Когда: State machines, enum configs.
WeakHashMap<K, V>
Описание: HashMap с weak keys (GC может удалить entry, если ключ недостижим).
Особенности: Для кэшей, где память критична.
Big O: O(1).
Нюансы: Values strong, cleanup не мгновенный.
Когда: Canonicalizing mappings (interning).
Полезные советы для новичков
HashMap 95% случаев: Начните с неё.
LinkedHashMap для кэша: removeEldestEntry для LRU.
TreeMap для сортировки: Comparator для reverse.
Custom ключи: IDE генерирует equals/hashCode.
Initial capacity: new HashMap<>(expectedSize) для избежания ресайза.
Ошибки: NPE в TreeMap с null-ключом; ClassCast в TreeMap без Comparable.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
Описание: Реализация SortedMap<K, V> на красно-черном дереве (red-black tree). Ключи всегда отсортированы.
Внутренняя структура: Дерево узлов с left/right/child ссылками, цветом для баланса.
Big O: O(log n) для put/get/remove/containsKey.
Особенности:
Порядок: Сортировка по ключам (Comparable или Comparator).
Null-ключ: Нет (NPE).
Null-значение: Да.
Thread-safe: Нет.
Нюансы:
Comparator: new TreeMap<>(comparator) для custom сортировки.
Дополнительные методы: firstKey(), lastKey(), headMap(K to), tailMap(K from), subMap.
Custom ключи: Comparable<K> или Comparator.
Баланс: Автоматический, O(log n) гарантировано.
Пример:
javaimport java.util.TreeMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new TreeMap<>();
map.put(3, "Три");
map.put(1, "Один");
map.put(2, "Два");
for (Integer key : map.keySet()) {
System.out.println(key + ": " + map.get(key)); // 1: Один, 2: Два, 3: Три
}
System.out.println(map.firstKey()); // 1
}
}
Когда использовать: Отсортированные ключи (диапазонные запросы, алфавитный словарь).
Остальные реализации: Hashtable, IdentityHashMap, EnumMap, WeakHashMap
Hashtable<K, V> (устаревшая)
Описание: Первая Map в Java (1.0), synchronized версия HashMap.
Особенности: Thread-safe (synchronized методы), нет null, порядок нет.
Big O: O(1).
Нюансы: Медленнее HashMap (locks на каждый метод), legacy — используйте ConcurrentHashMap.
Когда: Только legacy код.
IdentityHashMap<K, V>
Описание: HashMap с == вместо equals/hashCode (по ссылке).
Особенности: Для объектов, где важна идентичность (graph algorithms).
Big O: O(1).
Нюансы: Load factor 0.5, double hash для коллизий.
Когда: Редко, для identity сравнения.
EnumMap<K extends Enum<K>, V>
Описание: Оптимизированная Map для enum ключей (массив вместо хэш).
Особенности: O(1), порядок enum, нет null-ключа.
Нюансы: Ключи — enum, values any.
Когда: State machines, enum configs.
WeakHashMap<K, V>
Описание: HashMap с weak keys (GC может удалить entry, если ключ недостижим).
Особенности: Для кэшей, где память критична.
Big O: O(1).
Нюансы: Values strong, cleanup не мгновенный.
Когда: Canonicalizing mappings (interning).
Полезные советы для новичков
HashMap 95% случаев: Начните с неё.
LinkedHashMap для кэша: removeEldestEntry для LRU.
TreeMap для сортировки: Comparator для reverse.
Custom ключи: IDE генерирует equals/hashCode.
Initial capacity: new HashMap<>(expectedSize) для избежания ресайза.
Ошибки: NPE в TreeMap с null-ключом; ClassCast в TreeMap без Comparable.
#Java #для_новичков #beginner #Map #HashMap #LinkedHashMap #TreeMap #Hashtable #IdentityHashMap #EnumMap #WeakHashMap
👍2
  