Задать лимит размера к динамическому списку List без использования if?

У меня есть некий список животных(List<T> animals), где я бы хотела при каждом добавлении нового животного ограничить список без использования if else

public class Nursery <T> {

    private int maxSize;
    private List<T> animals = new ArrayList<>(maxSize);

    public void addAnimal(T animal) throws FullSizeException {
        if (animals.size() < maxSize) {
            animals.add(animal);
        } else {
            throw new FullSizeException();
        }
    }

Есть ли какие-то варианты?

И не понимаю почему этого недостаточно = new ArrayList<>(maxSize); - если я и так указываю размер, то зачем еще if else


Ответы (3 шт):

Автор решения: talex moved to Codidact

Параметр в new ArrayList<>(maxSize) задает начальное значение размера внутреннего буфера.

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

К сожалению в JDK нет стандартного класса для твоих нужд.

→ Ссылка
Автор решения: Kromster

Непонятно откуда вы взяли maxSize. Открыл документацию, там написано:

ArrayList(int initialCapacity)

initialCapacity переводится как "начальная ёмкость".


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

→ Ссылка
Автор решения: Nowhere Man

Что касается вопроса:

почему этого недостаточно = new ArrayList<>(maxSize); - если я и так указываю размер, то зачем еще if else

см. ответ на подобный вопрос: "Создать ArrayList<Integer> с фиксированной длиной":

В конструкторе ArrayList(int initialCapacity) задаётся НЕ размер, а ёмкость создаваемого списка, чтобы слегка оптимизировать заполнение списка заранее известным количеством элементов. Сам же список создаётся пустым:

public ArrayList(int initialCapacity)
Constructs an empty list with the specified initial capacity.

Там же описаны варианты реализации неизменяемых списков.

Однако, если нужно иметь динамический список для которого методы add, remove и т.п. должны работать, придётся использовать какой-то декоратор / собственную реализацию на основе ArrayList и переопределить методы для добавления элементов add(T item), add(int index, T item), addAll(Collection<? extends T> c), addAll(int index, Collection<? extends T> c), которые будут использовать метод checkSize для проверки нового размера списка:

public class MaxSizeList<T> extends ArrayList<T> {

    private final int maxSize;

    public MaxSizeList(int maxSize) {
        super(maxSize);
        this.maxSize = maxSize;
    }

    @Override
    public boolean add(T item) {
        checkSize(1);
        return super.add(item);     
    }

    @Override
    public void add(int index, T item) {
        checkSize(1);
        super.add(index, item);
    }

    // также переопределить addAll
    @Override
    public boolean addAll(Collection<? extends T> c) {
        checkSize(c.size());
        return super.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        checkSize(c.size());
        return super.addAll(index, c);
    }

    private void checkSize(int countToAdd) {
        if (size() + countToAdd > maxSize) {
            throw new FullSizeException("Total size cannot exceed " + maxSize);
        }
    }
}

Следует заметить, что при такой реализации исключение FullSizeException должно быть непроверяемым (unchecked):

public class FullSizeException extends RuntimeException {
    public FullSizeException(String msg) {
        super(msg);
    }
}
→ Ссылка