Список, который сам меняет размер
У обычного массива в Java фиксированная длина: выберете десять ячеек - и у вас навсегда останется десять ячеек. ArrayList - это альтернатива с изменяемым размером из java.util: он растёт, когда вы добавляете, и уменьшается, когда вы удаляете, и несёт в себе удобные методы для того, что вы действительно делаете со списком.
Обратите внимание на тип в угловых скобках - List<String> - который сообщает компилятору, что этот список хранит значения String. Скобки <> («ромб») справа позволяют Java вывести тот же тип, не повторяя его. И учтите, что вы импортируете java.util.ArrayList; по умолчанию он недоступен.
Объявляйте как List, создавайте как ArrayList
Почти всегда переменную типизируют через интерфейс List, а не через конкретный ArrayList:
List<String> names = new ArrayList<>();
Это хорошая привычка, а не правило. Программирование на интерфейс List означает, что остальной части кода неважно, какую реализацию списка вы использовали, поэтому позже вы можете заменить её на другую, не трогая его. В повседневном использовании обе ведут себя одинаково.
Добавление, получение и изменение
add(value)добавляет в конец.add(index, value)вставляет в позицию, сдвигая последующие элементы вправо.get(index)читает элемент в позиции (отсчёт с нуля).set(index, value)перезаписывает существующий элемент.
Индексы отсчитываются с нуля, а get по индексу вне диапазона выбрасывает IndexOutOfBoundsException.
Удаление элементов
Существует классическая ловушка, когда список хранит Integer. remove(int) означает «удалить по индексу», а remove(Object) - «удалить по значению», поэтому:
List<Integer> nums = new ArrayList<>(List.of(10, 20, 30));
nums.remove(1); // удаляет индекс 1 -> значение 20
nums.remove(Integer.valueOf(20)); // удаляет значение 20
Оборачивайте значение в Integer.valueOf(...), когда имеете в виду «удалить это значение», а не «удалить этот индекс».
Размер, contains и поиск по индексу
List.of(...) быстро создаёт неизменяемый список; передача его в конструктор ArrayList даёт изменяемую копию, заполненную этими значениями.
Перебор ArrayList
Самый чистый цикл - это расширенный for («for-each»):
Когда вам нужен ещё и индекс, используйте цикл со счётчиком с size() и get(i):
Одно правило: не добавляйте и не удаляйте элементы из списка, пока его перебирает цикл for-each - это выбрасывает ConcurrentModificationException. Чтобы безопасно удалить совпадающие элементы, используйте removeIf:
Сортировка
Collections.sort упорядочивает список на месте, используя естественный порядок (по алфавиту для строк, по числам для чисел):
Для произвольной сортировки передайте Comparator в list.sort(...) - например, names.sort(Comparator.comparingInt(String::length)), чтобы отсортировать по длине.
ArrayList хранит объекты, а не примитивы
Нельзя написать ArrayList<int>. Дженерики работают только с объектными типами, поэтому используйте класс-обёртку Integer, Double, Boolean и так далее:
Автоупаковка (autoboxing) в Java преобразует за вас int в Integer и обратно, так что это читается естественно - просто помните, что сам список хранит объекты Integer.
Далее: HashMap
ArrayList - подходящий инструмент, когда вам важны порядок и позиция. Когда нужно искать значения по ключу - имя пользователя к пользователю, код товара к цене - вам нужен HashMap, которому посвящена следующая страница.
Часто задаваемые вопросы
Как создать ArrayList в Java?
Объявите его с типом элементов в угловых скобках и вызовите конструктор: ArrayList<String> names = new ArrayList<>();. Скобки <> справа (ромб) позволяют Java вывести тип. Обычно переменную типизируют через интерфейс List: List<String> names = new ArrayList<>();.
В чём разница между массивом и ArrayList в Java?
У обычного массива фиксированная длина, заданная при создании, и он может хранить примитивы, такие как int. ArrayList автоматически растёт и уменьшается по мере добавления и удаления элементов, хранит только объекты (поэтому int становится Integer) и предоставляет методы вроде add, remove, contains и size. Используйте массив для примитивных данных фиксированного размера; используйте ArrayList, когда размер меняется.
Как удалить элемент из ArrayList?
Вызовите remove(index), чтобы удалить по позиции, или remove(object), чтобы удалить первый совпадающий элемент. Будьте осторожны со списками Integer: list.remove(2) удаляет индекс 2, тогда как list.remove(Integer.valueOf(2)) удаляет значение 2. Чтобы удалять во время перебора, используйте remove() у Iterator или removeIf(...), чтобы избежать ConcurrentModificationException.