Гид по технологиям

ArrayList в Java — практическое руководство

6 min read Java Обновлено 09 Jan 2026
ArrayList в Java — практическое руководство
ArrayList в Java — практическое руководство

Что такое ArrayList

ArrayList — это реализуемая на основе массива реализация интерфейса List из пакета java.util. Она хранит элементы в упорядоченном виде и автоматически изменяет размер при добавлении или удалении элементов. Ключевые возможности:

  • Доступ по индексу (get/set).
  • Динамическое изменение размера (добавление/удаление).
  • Поддержка коллекционных операций (addAll, removeAll и т. д.).

Определение: ArrayList — это изменяемый, индексируемый контейнер для объектов в Java.

Основные подклассы AbstractList

AbstractList реализует List и служит базой для нескольких реализаций коллекций. Близкие классы:

  • LinkedList — оптимизирован для вставки и удаления в середине списка.
  • Vector — похож на ArrayList, но синхронизирован; подходит для многопоточных окружений старого кода.
  • Stack — устаревшая структура, расширяет Vector и обеспечивает LIFO-операции.

Эти классы выходят за рамки данного руководства. Здесь мы сосредоточимся на общем ArrayList.

Иерархия классов ArrayList в Java Collections

Изображение: диаграмма иерархии классов коллекций Java с выделением ArrayList и его родственников.

Создание ArrayList

Создать ArrayList очень просто. Сначала импортируйте пакет java.util.ArrayList (или java.util.*). Далее можно использовать один из конструкторов.

Без параметров (пустой список):

ArrayList alist = new ArrayList();

Если заранее известна примерная ёмкость, можно указать initial capacity. Это рекомендация для внутреннего массива и иногда даёт небольшое преимущество по производительности при больших объёмах данных.

ArrayList alist = new ArrayList(8);

Новый ArrayList с заполненными и пустыми слотами

Изображение: схематичное представление нового ArrayList с выделенными пустыми индексами.

Наполнение ArrayList

Добавление элементов в конец

Для добавления одиночного элемента в конец используйте add(). Пример:

ArrayList alist = new ArrayList();  
alist.add("apple");  
alist.add("banana");  
alist.add("cantaloupe");  
alist.add("orange");  
System.out.println(alist);  

Вывод в консоль:

[apple, banana, cantaloupe, orange]

Метод size() возвращает текущее количество элементов:

System.out.println("Number of elements in the arraylist: " + alist.size());
// Number of elements in the arraylist: 4

Добавление элементов в конец ArrayList

Изображение: визуализация добавления элементов в конец динамического массива.

Добавление по указанному индексу

Чтобы вставить элемент на конкретную позицию, используйте перегруженный add(index, item):

alist.add(3, "grapes");  
System.out.println(alist);  

Вывод:

[apple, banana, cantaloupe, grapes, orange]

Помните: индексация начинается с нуля.

Добавление коллекции целиком

Вы можете добавить все элементы из другой коллекции через addAll(). Например:

List items = Arrays.asList("pear", "cherry");  
alist.addAll(items);  
System.out.println(alist);  
// [apple, banana, cantaloupe, grapes, orange, pear, cherry]

Также можно указать индекс, куда вставить коллекцию: alist.addAll(2, items);

Доступ к элементам

Доступ по индексу

Если известен индекс, используйте get():

String item = alist.get(2);  
System.out.println("Item at index 2 is: " + item);  
// Item at index 2 is: cantaloupe

Поиск элемента

indexOf() возвращает индекс первого вхождения или -1, если элемент не найден:

int index = alist.indexOf("orange");
if (index < 0) {
    System.out.println("Item \"orange\" not found");
} else {
    System.out.println("Item \"orange\" found at index " + index);
}

// Item "orange" found at index 4

Если элемента нет, indexOf вернёт -1.

Итерация по ArrayList

Частая операция — проход по всем элементам. Самые распространённые способы:

  • Enhanced for loop (foreach):
for (String fruit : alist) {  
    System.out.println("Found fruit \"" + fruit + "\"");  
}
  • Iterator: позволяет безопасно удалять элементы во время прохода. В примере ниже создаётся копия списка, и на ней выполняется итерация с удалением элементов, начинающихся на “c”:
ArrayList blist = new ArrayList(alist);  
for (Iterator iter = blist.iterator() ; iter.hasNext() ; ) {  
    String fruit = iter.next();  
    if (fruit.startsWith("c")) {  
        iter.remove();  
    } else {  
        System.out.println("Keeping \"" + fruit + "\"");  
    }  
}

// Keeping "apple"
// Keeping "banana"
// Keeping "grapes"
// Keeping "orange"
// Keeping "pear"

Важно: нельзя изменять коллекцию напрямую (например, alist.remove(i)) во время итерации с использованием foreach — это приведёт к ConcurrentModificationException.

Замена и удаление элементов

Замена

set(index, item) заменяет элемент по индексу:

alist.set(5, "pineapple");  
System.out.println(alist);
// [apple, banana, cantaloupe, grapes, orange, pineapple, cherry]

Удаление

remove(index) возвращает удалённый элемент, remove(object) возвращает boolean — true, если элемент был найден и удалён:

String fruit = alist.remove(2);  
System.out.println("Removed element at 2: " + fruit);  
// Removed element at 2: cantaloupe

fruit = "grapes";  
System.out.println("Remove " + fruit + " from the list? " + alist.remove(fruit));
// Remove grapes from the list? true

Практическая ценность и выбор структуры данных

ArrayList отлично подходит, когда вам нужен быстрый доступ по индексу и часто выполняются операции чтения или добавления в конец. Однако существуют сценарии, когда он не лучший выбор.

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

  • Частые вставки/удаления в середине большого списка (LinkedList или специализированные структуры лучше).
  • Требуется хранение пар «ключ-значение» (используйте Map, например HashMap).
  • Жёсткие требования по многопоточности: лучше использовать ConcurrentLinkedQueue/CopyOnWriteArrayList или синхронизацию.

Альтернативы

  • LinkedList — эффективен для вставок/удалений в середине списка.
  • HashMap/TreeMap — для доступа по ключу.
  • ArrayDeque — для стека/очереди с быстрой работой с концами.
  • CopyOnWriteArrayList — для сценариев с частыми чтениями и очень редкими модификациями в многопоточном окружении.

Ментальные модели и эвристики выбора

  • Если 80% операций — чтение и случайный доступ, выбирайте ArrayList.
  • Если 50% операций — вставки/удаления в середине, выбирайте LinkedList.
  • Если нужен уникальный ключ для каждого элемента — используйте Map.

Шпаргалка по методам ArrayList

МетодЧто делает
add(E e)Добавляет элемент в конец
add(int index, E e)Вставляет элемент по индексу
addAll(Collection c)Добавляет все элементы из коллекции
get(int index)Возвращает элемент по индексу
set(int index, E e)Заменяет элемент по индексу
remove(int index)Удаляет и возвращает элемент по индексу
remove(Object o)Удаляет первый найденный объект, возвращает boolean
indexOf(Object o)Возвращает индекс или -1
size()Возвращает количество элементов
clear()Очищает список

Критерии приёмки при выборе ArrayList

  • Производительность доступа по индексу соответствует требованиям (O(1)).
  • Частота вставок/удалений в середине низкая.
  • Память: допустим небольшой рост внутреннего массива при добавлении.
  • Блокировка/синхронизация: либо не требуется, либо предусмотрены внешние механизмы.

Ролевые чек-листы

Разработчик:

  • Проверить, что операции по индексу критичны.
  • Использовать типизированные коллекции (Generics).
  • Обрабатывать возможные IndexOutOfBoundsException.

Архитектор:

  • Оценить временную сложность операций.
  • Решить, нужна ли потокобезопасность.
  • Рассмотреть альтернативы для больших наборов данных.

Тестировщик:

  • Тесты на добавление/удаление/многопоточный доступ.
  • Проверить реакцию на null-элементы (ArrayList допускает null).

Примеры типичных ошибок и крайние случаи

  • ConcurrentModificationException при модификации коллекции во время итерации через foreach.
  • Использование ArrayList для огромных объёмов с частыми вставками в середину — плохая производительность.
  • Ожидание фиксированной ёмкости: внутренний массив расширяется автоматические, но это может влиять на использование памяти.

Пример небольшого рабочего сценария

Полный пример: создание списка, добавление, поиск, удаление и итерация.

import java.util.*;

public class Example {
    public static void main(String[] args) {
        ArrayList alist = new ArrayList();
        alist.add("apple");
        alist.add("banana");
        alist.add("orange");

        System.out.println("Initial: " + alist);

        // Вставка
        alist.add(1, "kiwi");
        System.out.println("After insert: " + alist);

        // Поиск
        int i = alist.indexOf("orange");
        System.out.println("orange at: " + i);

        // Удаление
        alist.remove("banana");
        System.out.println("After remove: " + alist);

        // Итерация
        for (String s : alist) {
            System.out.println("Fruit: " + s);
        }
    }
}

Быстрая проверка совместимости и миграции

  • Код, использующий List интерфейс, легко переключается между ArrayList и LinkedList.
  • Для многопоточных систем рассмотрите Collection.synchronizedList(new ArrayList<>()) или специализированные concurrent-классы.

Security и приватность

ArrayList сам по себе не добавляет новых рисков безопасности, но помните:

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

Полезные подсказки и рекомендации

  • При массовом добавлении элементов заранее задайте initial capacity, чтобы уменьшить количество перераспределений.
  • Используйте интерфейс List в сигнатурах методов — это повысит гибкость.

Заключение

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

Important: всегда анализируйте требования по производительности и многопоточности перед выбором реализации коллекции.

Краткое резюме:

  • ArrayList хорош для случайного доступа и добавления в конец.
  • Для частых вставок в середину используйте LinkedList.
  • Для доступа по ключу используйте Map.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство