Интерфейс List и класс ArrayList в Java - Вопросы

Всего: 5 вопросов

1. 

Чем ёмкость (capacity) ArrayList отличается от его размера (size)?

Ёмкость — это длина внутреннего массива Object[], а size() — количество реально добавленных элементов. new ArrayList<>() с Java 8 создаёт пустой массив и выделяет 10 ячеек при первом add(); когда массив заполнен, он заменяется новым примерно в 1,5 раза больше (10, 15, 22, 33...).

Ёмкость не делает индексы доступными: после new ArrayList<>(10) размер списка равен 0, и list.set(0, "Java") или list.get(0) бросают IndexOutOfBoundsException. Заранее увеличить ёмкость можно через конструктор или ensureCapacity(n), освободить лишние ячейки — через trimToSize(); оба метода есть только у класса ArrayList.

2. 

Какие реализации интерфейса List есть в Java и какую выбирать по умолчанию?

Основные реализации: ArrayList — динамический массив, get(i) за O(1); LinkedList — двусвязный список, доступ по индексу за O(n); Vector (и Stack) — устаревший класс с синхронизированными методами; CopyOnWriteArrayList — потокобезопасный список, копирующий массив при каждой записи; List.of() и List.copyOf() — неизменяемые списки без null.

По умолчанию выбирают ArrayList: у него самый быстрый доступ по индексу и меньше расход памяти. Вставка и удаление в начале или середине у него стоят O(n), потому что хвост массива сдвигается.

3. 

Чем отличаются remove(int index) и remove(Object o) у List<Integer>?

remove(int index) удаляет элемент по позиции и возвращает его, remove(Object o) удаляет первое вхождение значения и возвращает true/false. Если аргумент — литерал int, компилятор выбирает remove(int) без автоупаковки.

Для new ArrayList<>(List.of(10, 20, 30)) вызов remove(1) удалит 20 и оставит [10, 30], а remove(10) бросит IndexOutOfBoundsException. Чтобы удалить само число, передают объект: remove(Integer.valueOf(10)).

4. 

Что возвращают indexOf(), lastIndexOf() и contains() у List и почему для своих классов нужен equals()?

indexOf(o) возвращает индекс первого вхождения, lastIndexOf(o) — последнего, оба возвращают -1, если элемента нет. contains(o) возвращает только true или false. Все три метода перебирают список линейно, за O(n).

Элементы сравниваются через equals(). Если в своём классе он не переопределён, сравниваются ссылки, и объект с теми же значениями полей не будет найден. Для частого поиска без учёта порядка быстрее HashSet, у которого contains() работает в среднем за O(1).

5. 

Что возвращает метод subList(from, to) и чем он опасен?

subList(from, to) возвращает не копию, а представление (view) элементов с индекса from до to - 1. Изменения через него видны в исходном списке и наоборот: list.subList(1, 3).clear() удаляет этот диапазон из самого списка.

После структурного изменения исходного списка (add(), remove()) обращение к старому subList бросает ConcurrentModificationException, а при from > to — IllegalArgumentException. Независимую часть списка получают копированием: new ArrayList<>(list.subList(1, 3)).

Страница 1 из 1