Есть ли ограничения на размер ArrayList в Java?
Что проверяют
Знаете ли вы, как ArrayList устроен внутри, и можете ли отделить формальный предел от практического. Следом обычно спрашивают, как растёт внутренний массив и сколько памяти займёт список из миллиарда элементов.
Как отвечать
Внутри ArrayList лежит обычный массив Object[] elementData, отсюда все ограничения:
- формальный предел: индекс массива и
size()имеют типint, поэтому элементов не большеInteger.MAX_VALUE, то есть 2 147 483 647; - предел JVM: HotSpot обычно не выделяет массив ровно такой длины. JDK при росте держит мягкий потолок на 8 элементов ниже
Integer.MAX_VALUE, а запрос сверх возможностей VM заканчиваетсяOutOfMemoryError: Requested array size exceeds VM limit; - практический предел: память кучи. Массив хранит ссылки: со сжатыми указателями (
UseCompressedOops, включены по умолчанию для куч до 32 ГБ) это 4 байта на ссылку, без них 8. Два миллиарда ссылок это около 8 ГБ только на массив, плюс сами объекты: упакованныйIntegerзанимает ещё порядка 16 байт.
Дальше расскажите про рост. new ArrayList<>() сначала держит пустой массив и выделяет 10 ячеек при первом add. Когда место кончается, ёмкость растёт в полтора раза (oldCapacity + (oldCapacity >> 1)), элементы копируются в новый массив через Arrays.copyOf. В момент копирования живут оба массива, поэтому пиковое потребление примерно в 2,5 раза выше полезного.
Отсюда советы: если размер известен заранее, задайте ёмкость в конструкторе или вызовите ensureCapacity(), после наполнения лишнее отрезает trimToSize(). Для сотен миллионов чисел берите примитивные массивы или коллекции вроде IntArrayList из fastutil, а данные, которые не помещаются в кучу, обрабатывайте потоком или частями.
Где спотыкаются
Отвечают «ограничений нет, только память». Предел int в индексе есть всегда, и его стоит назвать первым.
Путают размер и ёмкость: new ArrayList<>(100) создаёт пустой список, и get(0) бросит IndexOutOfBoundsException.
Говорят, что массив удваивается. Так по умолчанию растёт Vector, у ArrayList множитель 1,5.