Для чего предназначен ArrayList в Java?

«Для чего предназначен ArrayList в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

ArrayList — это реализация интерфейса List на основе динамически изменяемого массива. Он используется, когда необходим частый доступ к элементам по индексу и работа с коллекцией, размер которой может меняться.

Основные преимущества и характеристики:

  • Быстрый доступ по индексу (O(1)) — благодаря внутреннему массиву elementData[].
  • Автоматическое управление емкостью — при добавлении элементов сверх текущей емкости (capacity) массив автоматически увеличивается (обычно в 1.5 раза).
  • Удобный API — методы add(), get(), set(), remove().

Пример использования:

import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {
    public static void main(String[] args) {
        // Создание ArrayList с типизацией (Generics)
        List<String> languages = new ArrayList<>();

        // Добавление элементов (автоматическое расширение при необходимости)
        languages.add("Java");    // Внутренний массив: ["Java"]
        languages.add("Kotlin");  // ["Java", "Kotlin"]
        languages.add(1, "Python"); // Вставка по индексу 1: ["Java", "Python", "Kotlin"]

        // Быстрый доступ по индексу
        String firstLang = languages.get(0); // "Java" (O(1))

        // Итерация
        for (String lang : languages) {
            System.out.println(lang);
        }
        // Или с помощью Stream API
        languages.stream().filter(l -> l.startsWith("J")).forEach(System.out::println);
    }
}
Сравнение производительности (Big O): Операция ArrayList LinkedList Примечание для ArrayList
get(int index) O(1) O(n) Прямой доступ к элементу массива.
add(E element) O(1)* O(1) *Амортизированная O(1), но O(n) при расширении массива.
add(int index, E element) O(n) O(1) Требуется сдвиг всех последующих элементов.
remove(int index) O(n) O(1) Требуется сдвиг всех последующих элементов.
set(int index, E element) O(1) O(n) Простая замена элемента в массиве.

Когда использовать ArrayList:

  • Преобладают операции чтения (get, set, iterate).
  • Часто требуется доступ по индексу.
  • Размер коллекции изменяется, но вставки/удаления происходят преимущественно в конце списка.

Когда выбрать другую реализацию:

  • Для частых вставок/удалений в середину списка используйте LinkedList.
  • Для фиксированного размера и максимальной производительности рассмотрите обычный массив (T[]).
  • Для потокобезопасности используйте CopyOnWriteArrayList или синхронизированные обертки (Collections.synchronizedList).