logo

Реализация очереди фиксированного размера в Java: автоочистка

Быстрый ответ

LinkedBlockingDeque станет идеальной реализацией для построения такой очереди с пределом по вместимости. Установив максимальный размер, вы будете иметь очередь, которая сама избавляется от самых старых элементов при превышении указанного лимита. Вот как это сделать:

Java
Скопировать код
// Задаем предел размера очереди
int capacity = 10;

// Создаем очередь с ограниченным размером
LinkedBlockingDeque<Integer> queue = new LinkedBlockingDeque<>(capacity);

// Добавляем новый элемент
queue.addLast(element);

// Управляем размером очереди
if (queue.size() > capacity) {
    queue.removeFirst();
}

Так, очередь всегда будет сохранять установленный размер, удаляя при этом старые элементы.

Реализация фиксированного размера очереди с помощью LinkedHashMap

LinkedHashMap в Java — это мощный инструмент, который можно сконфигурировать для создания очереди с фиксированным размером. Для автоматического удаления старых элементов достаточно настроить метод removeEldestEntry.

Java
Скопировать код
// Устанавливаем размер вместимости
int capacity = 10;

// Используем LinkedHashMap для создания очереди
LinkedHashMap<Integer, Boolean> map = new LinkedHashMap<Integer, Boolean>(capacity, 0.75F, true) {
    protected boolean removeEldestEntry(Map.Entry<Integer, Boolean> eldest) {
        // Если размер превышает вместимость, удаляем старый элемент
        return size() > capacity;
    }
};

Библиотеки на помощь: Guava и Apache Commons

Не нужно изобретать велосипед: EvictingQueue из библиотеки Google Guava и CircularFifoQueue от Apache Commons — прекрасны для создания очередей с автоматическим удалением устаревших элементов.

Java
Скопировать код
// Стандартная очередь от Guava
EvictingQueue<Integer> evictingQueue = EvictingQueue.create(capacity);

// Циклическая очередь от Apache
CircularFifoQueue<Integer> fifoQueue = new CircularFifoQueue<>(capacity);

Заметьте: оба типа данных не поддерживают null-значения.

Простая реализация с помощью ArrayDeque

Если вам нужна простота, выберите ArrayDeque. Его нужно только немного адаптировать, добавив методы для контроля за размером очереди:

Java
Скопировать код
ArrayDeque<Integer> deque = new ArrayDeque<>(capacity);

// Переопределите метод добавления для контроля размера
public boolean add(Integer e) {
    if (deque.size() == capacity) {
        deque.pollFirst();
    }
    return deque.offerLast(e);
}

Рекомендации по выбору реализации

При выборе реализации необходимо ориентироваться на требования к потокобезопасности, производительности и поддержке null-значений:

  • LinkedBlockingDeque: Потокобезопасна, но может уступать по скорости из-за необходимости синхронизации.
  • Настройка LinkedHashMap: Требует некоторого усилия для наследования и переопределения методов.
  • Библиотеки сторонних разработчиков: Простота добавления зависимости и использования готового решения.
  • Модификация ArrayDeque: Быстра и лаконична, но подходит только для не потокобезопасных задач.

Создаем собственную очередь путем наследования от AbstractQueue

Если вам нужен полный контроль над функционалом, вы можете наследовать AbstractQueue и создать свою собственную очередь с фиксированным размером:

Java
Скопировать код
public class FixedSizeQueue<E> extends AbstractQueue<E> {
    // Настраивайте по своему усмотрению.
}

Полезные материалы

  1. Реализации BlockingQueue
  2. ArrayDeque
  3. EvictingQueue из Guava
  4. PriorityBlockingQueue
  5. Документация ConcurrentLinkedQueue JavaDoc
  6. Использование LinkedList как очереди в Java