
ArrayList позволяет хранить любые значения в том числе и null.
Внутри себя ArrayList хранит элементы в обычном массиве. Если ArrayList необходимо увеличить или уменьшить свой размер, он создаёт новый массив и копирует в него данные.
Структура ArrayList
Размер массива, используемого для хранения элементов в списке называется ёмкостью (capacity). При создании нового объекта ArrayList по умолчанию создаётся массив размером 10 элементов. Эту величину можно изменить, передав нужное значение в конструктор (параметр capacity).
ArrayList< String > list = new ArrayList<>(50); // capacity = 50
Когда свободные ячейки заканчиваются, создаётся новый массив размером (oldCapacity * 3) / 2 + 1, т.е. чуть больше чем в 1,5 раза от изначального размера.Добавление элемента в конец массива происходит за константное время О(1). Если же в массиве не хватает свободного места, это время увеличивается.
При вставке элемента в середину и при удалении элемента по индексу всегда создаётся новый массив. Это увеличивает временные затраты на выполнение операции.
При удалении элемента по значению, в цикле просматриваются все элементы списка, до тех пор пока не будет найдено соответствие. Удален будет лишь первый найденный элемент. Однако, ёмкость по умолчанию не уменьшается. Чтобы её уменьшить, нужно явно вызвать метод trimToSize(), иначе возможны утечки памяти.
ArrayList не синхронизирован. Чтобы его синхронизировать, нужно вызвать метод:
List list = Collections.synchronizedList(new ArrayList());
Но если необходимо работать с синхронизированным списком в режиме итераций, тогда нужно выполнять её в синхронизированном блоке.Подробная статья об ArrayList.