Чем ArrayList отличается от LinkedList и что брать по умолчанию?
- Когда использовать LinkedList?
ArrayList — динамический массив: доступ по индексу O(1), добавление в конец амортизированно O(1). LinkedList — двусвязный список: O(1) только при вставке или удалении у уже известного узла. По умолчанию — ArrayList.
- Поиск позиции в LinkedList — O(n), поэтому add(i, x) линейный у обоих
- ArrayList компактнее и дружелюбнее к кэшу процессора — почти всегда быстрее на практике
- Для очереди и стека — ArrayDeque, а не LinkedList
А ещё LinkedList оправдан редко: много вставок через ListIterator в середину огромного списка
Подробно
ArrayList хранит элементы в массиве. get(i) — прямой доступ O(1). add(e) в конец — O(1) амортизированно: когда массив заполнен, он растёт в 1,5 раза с копированием, но копирования редки. Вставка и удаление в середине — O(n): сдвиг хвоста через System.arraycopy (быстрый блочный сдвиг памяти).
LinkedList — двусвязный список узлов {prev, item, next}. get(i) — O(n): обход от ближайшего конца. Вставка и удаление — O(1), если узел уже найден (через ListIterator) или это края списка. add(i, x) по индексу сначала ищет позицию — O(n).
Почему ArrayList почти всегда выигрывает:
- элементы массива лежат подряд — процессор подгружает их в кэш блоками, а узлы LinkedList разбросаны по куче — промах кэша на каждом шаге;
- каждый узел — отдельный объект с заголовком и двумя ссылками: в разы больше памяти и работы сборщику;
- сдвиг массива
arraycopyочень быстрый даже на тысячах элементов.
Когда LinkedList: в новом коде — почти никогда. Для очередей и стеков есть ArrayDeque (кольцевой массив). Исключение — частые вставки и удаления в середине при обходе итератором огромного списка, и то стоит измерить.
Что хотят услышать
- Устройство обеих реализаций.
- Сложность доступа, вставки в конец и в середину.
- Почему на практике ArrayList быстрее: кэш и память.
- ArrayDeque для очередей.
Частые ошибки
- «LinkedList быстрее для вставки в середину» без учёта поиска позиции.
- Использовать LinkedList как очередь вместо ArrayDeque.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗ArrayList не умеет расти, LinkedList — динамический
- ✗По умолчанию LinkedList: вставка в любое место за O(1), а ArrayList каждый раз копирует массив
- ✓По умолчанию ArrayList: индекс O(1) и кэш-локальность; LinkedList почти всегда медленнее
- ✗Они одинаковы по производительности
Что спросят дальше
- Как растёт ArrayList при добавлении?
- Когда LinkedList реально оправдан?
Разбор темы
- ArrayList: динамический массив изнутри
Бэкенд-массив, рост в 1.5×, амортизированная O(1), стоимость вставки/удаления и когда массив лучше.
- Collections Framework: карта и выбор структуры
Иерархия интерфейсов, сложности операций основных структур, неизменяемые коллекции и принцип выбора по паттерну доступа.
- LinkedList и миф о дешёвой вставке
Двусвязные узлы, реальная стоимость операций, cache locality и почему ArrayList/ArrayDeque почти всегда лучше.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.