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

Java ArrayList: создание и использование

5 min read Java Обновлено 28 Dec 2025
Java ArrayList — руководство и шпаргалка
Java ArrayList — руководство и шпаргалка

ArrayList — это удобный динамический массив в Java: легко создавать, менять размер, добавлять, удалять и перебирать элементы. В статье показаны примеры создания, добавления, доступа, замены и удаления элементов, советы о производительности и когда лучше выбрать альтернативы.

Что такое ArrayList

Изображение: диаграмма иконок, иллюстрирующая ArrayList

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

  • Динамическая структура: автоматически меняет внутренний массив при добавлении или удалении элементов.
  • Индексированный доступ: поддерживает получение/замену по индексу за константное время в среднем.
  • Поддерживает CRUD-операции: add, get, set, remove, indexOf и т.д.

Определение терминов в одну строку:

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

Подклассы AbstractList и родственные структуры

Иллюстрация иерархии класса ArrayList в коллекциях Java

AbstractList реализует интерфейс List и даёт основу для структур данных, включая ArrayList. Ближайшие классы и их частые случаи применения:

  • LinkedList — эффективная вставка/удаление в середине списка; лучше при частых операциях вставки/удаления по середине.
  • Vector — схож с ArrayList, но синхронизирован; используется в многопоточных устаревших приложениях.
  • Stack — расширяет Vector, реализует LIFO-стек; чаще заменяется Deque/ArrayDeque.

Эти классы затрагиваются лишь поверхностно: фокус статьи — базовая работа с ArrayList.

Создание ArrayList

Создание пустого ArrayList требует импорта:

import java.util.ArrayList;

Пустой ArrayList через конструктор без аргументов:

ArrayList alist = new ArrayList();

Указание начальной ёмкости (hint для выделения памяти):

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());

Добавление в заданный индекс

Чтобы вставить элемент в конкретную позицию, передайте индекс и элемент:

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

Результат:

[apple, banana, cantaloupe, grapes, orange]

Напоминание: индексы в Java начинаются с нуля.

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

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

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

Также есть перегрузка addAll(int index, Collection) для вставки коллекции в указанную позицию.

Иллюстрация: добавление элементов в конец ArrayList

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

Получение по индексу

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

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

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

Если индекс неизвестен, indexOf(element) вернёт позицию или -1, если элемент не найден:

System.out.println(alist);
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);
}

Если элемент отсутствует:

index = alist.indexOf("grape");
if (index < 0) {
    System.out.println("Item \"grape\" not found");
}
// Item "grape" not found

Итерация по ArrayList

Частая задача — пройтись по всем элементам.

  • Расширенный for-loop (рекомендуется для простого чтения):
for (String fruit : alist) {
    System.out.println("Found fruit \"" + fruit + "\"");
}
  • Iterator — нужен, если требуется безопасное удаление во время обхода:
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 + "\"");
    }
}

Iterator.remove() безопасно удаляет текущий элемент итерации и предотвращает ConcurrentModificationException.

Замена элементов

Метод set(index, element) заменяет значение по индексу:

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

Удаление элементов

remove(index) удаляет по индексу и возвращает удалённый элемент:

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

remove(Object) удаляет первое вхождение элемента и возвращает boolean:

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

Когда ArrayList подходит, а когда нет

Когда выбрать ArrayList:

  • Частые операции чтения и произвольный доступ по индексу.
  • Добавление в конец списка (амортизированное O(1)).
  • Когда необходим упорядоченный список с возможными дубликатами.

Когда не выбирать ArrayList:

  • Много вставок/удалений в середине списка — лучше LinkedList.
  • Нужна уникальная пара (ключ->значение) — лучше HashMap.
  • Высокая конкуренция потоков и требуется синхронизация — рассмотрите Concurrent collections или Vector только при совместимости с устаревшим кодом.

Альтернативы и сравнение (кратко)

  • LinkedList — лучше для частых вставок/удалений в середине; операции get(i) — O(n).
  • HashMap — хранение по ключу; быстрый доступ по ключу, порядок не гарантируется (используйте LinkedHashMap для упорядоченности).
  • ArrayDeque — более эффективный стек/очередь, чем Stack/Vector.

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

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

Правило большого пальца: оптимизируйте под наиболее частую операцию (чтение vs вставка/удаление).

Быстрый справочник (cheat sheet)

  • Создать: new ArrayList<Тип>();
  • Добавить: add(element), add(index, element)
  • Добавить коллекцию: addAll(collection), addAll(index, collection)
  • Получить: get(index)
  • Найти: indexOf(element)
  • Заменить: set(index, element)
  • Удалить: remove(index) или remove(object)
  • Размер: size()
  • Очистить: clear()

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

Для разработчика:

  • Проверить: нужен ли упорядоченный список или Map.
  • Указать тип (generics) для безопасности типов.
  • Задать начальную ёмкость, если известен ожидаемый размер.
  • Использовать Iterator.remove при удалении во время итерации.

Для ревьюера кода:

  • Убедиться, что операции не выполняют лишних копирований коллекций.
  • Проверить границы индексов и обработку исключений.
  • Оценить многопоточность: нужен ли synchronized/ConcurrentList.

Для архитектора:

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

Фактбокс с ключевыми моментами

  • ArrayList реализует List и основан на массиве.
  • get(index) — O(1) в среднем; вставка в конец — амортизированное O(1).
  • Вставка/удаление в середине — O(n).
  • indexOf — O(n).

Примеры неисправностей и когда подход ломается

  • ConcurrentModificationException: попытка модифицировать коллекцию вне Iterator во время итерации.
  • Падение производительности при частых вставках в середину: в этом случае LinkedList или специализированная структура окажутся быстрее.
  • Утечки памяти при хранении большого количества объектов: стоит рассмотреть хранение ссылок на объекты меньшего размера или потоковую обработку.

Небольшая методология миграции с ArrayList на альтернативы

  1. Замерить: профилируйте приложение и подтвердите узкие места.
  2. Проанализировать паттерн доступа: чтение/запись/удаление.
  3. Прототип: заменить ArrayList на LinkedList/Map/Deque в тестовом модуле.
  4. Тесты: убедиться в отсутствии регрессий и сохранении API.
  5. Внедрение постепенно, мониторинг метрик.

Простой алгоритм выбора (Mermaid)

flowchart TD
    A[Нужен упорядоченный список?] -->|Нет| B[Используйте Map 'HashMap/LinkedHashMap']
    A -->|Да| C[Частые вставки/удаления в середине?]
    C -->|Да| D[LinkedList]
    C -->|Нет| E[ArrayList]
    E --> F{Многопоточный доступ?}
    F -->|Да| G[Используйте Concurrent коллекции или синхронизацию]
    F -->|Нет| H[ArrayList — подходит]

Критерии приёмки

  • unit-тесты покрывают операции add/get/set/remove и проверки границ индексов.
  • нет ConcurrentModificationException в многопоточной среде (или используется безопасная стратегия).
  • производительность укладывается в требования нагрузки (латентность/пропускная способность).

Итог и рекомендации

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

Важно

  • Всегда указывайте дженерики (например, ArrayList), чтобы избежать непредвиденных ClassCastException.
  • При удалении во время итерации используйте Iterator.remove().

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

ArrayList — базовый инструмент коллекций Java: прост в использовании, гибок и эффективен для чтения и добавления в конец. Для других шаблонов доступа выбирайте соответствующие структуры.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

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

Как сделать слайдер для камеры за $35
Сделай сам

Как сделать слайдер для камеры за $35

Как стримить с телефона на ПК через OBS
Стриминг

Как стримить с телефона на ПК через OBS

Как удалить аккаунт Reddit — полное руководство
Инструкции

Как удалить аккаунт Reddit — полное руководство

Как выбрать камеру для влогинга
Видео

Как выбрать камеру для влогинга

Как сравнить процессоры CPU: практическое руководство
Hardware

Как сравнить процессоры CPU: практическое руководство

Отключить всплывающее «Открыть в приложении» на Reddit
Инструкция

Отключить всплывающее «Открыть в приложении» на Reddit