«1. Обзор

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

В этом уроке мы рассмотрим разницу между емкостью ArrayList и размером массива.

Мы также рассмотрим примеры того, когда мы должны инициализировать ArrayList с емкостью, а также преимущества и недостатки с точки зрения использования памяти.

2. Пример

Чтобы понять различия, давайте сначала попробуем оба варианта.

2.1. Размер массива

В java обязательно указывать размер массива при создании его нового экземпляра:

Integer[] array = new Integer[100]; 
System.out.println("Size of an array:" + array.length);

Здесь мы создали целочисленный массив размером 100, что привело к следующему результату

Size of an array:100

2.2. Емкость ArrayList

Теперь давайте создадим ArrayList с начальной емкостью 100:

List<Integer> list = new ArrayList<>(100);
System.out.println("Size of the list is :" + list.size());
Size of the list is :0

Поскольку элементы еще не добавлены, размер равен нулю.

list.add(10);
System.out.println("Size of the list is :" + list.size());
Size of the list is :1

Теперь давайте добавим элемент в список и проверим его размер:

3. Размер в массивах и ArrayList

Ниже приведены некоторые основные различия между размером массива и емкость ArrayList.

3.1. Изменение размера

Массивы имеют фиксированный размер. Как только мы инициализируем массив некоторым значением int в качестве его размера, он не может измениться. Размер и вместимость тоже равны друг другу.

Размер и емкость ArrayList не фиксированы. Логический размер списка изменяется в зависимости от вставки и удаления элементов в нем. Это управляется отдельно от физического размера хранилища. Кроме того, когда достигается пороговое значение емкости ArrayList, он увеличивает свою емкость, чтобы освободить место для большего количества элементов.

3.2. Распределение памяти

Память массива выделяется при создании. Когда мы инициализируем массив, он выделяет память в соответствии с размером и типом массива. Он инициализирует все элементы нулевым значением для ссылочных типов и значением по умолчанию для примитивных типов.

ArrayList изменяет распределение памяти по мере своего роста. Когда мы указываем емкость при инициализации ArrayList, он выделяет достаточно памяти для хранения объектов до этой емкости. Логический размер остается равным 0. Когда приходит время расширить емкость, создается новый, больший массив, и в него копируются значения.

Следует отметить, что существует специальный одноэлементный массив нулевого размера для пустых объектов ArrayList, что делает их создание очень дешевым. Также стоит отметить, что ArrayList внутренне использует массив ссылок на объекты.

4. Когда инициализировать ArrayList с емкостью

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

4.1. Построение большого списка-массива

Хорошо инициализировать список начальной емкостью, когда мы знаем, что он станет большим. Это предотвращает некоторые дорогостоящие операции роста при добавлении элементов.

Точно так же, если список очень большой, операции автоматического увеличения могут выделить больше памяти, чем необходимо для точного максимального размера. Это связано с тем, что сумма, которая будет увеличиваться каждый раз, рассчитывается как доля размера на данный момент. Таким образом, с большими списками это может привести к пустой трате памяти.

4.2. Построение небольших множественных списков ArrayList

Если у нас много небольших коллекций, то автоматическая емкость ArrayList может привести к большому проценту неиспользуемой памяти. Предположим, что ArrayList предпочитает размер 10 с меньшим количеством элементов, но мы сохраняем только 2 или 3. Это означает, что 70% потраченной впустую памяти, что может иметь значение, если у нас огромное количество этих списков.

Заранее указав емкость, можно избежать этой ситуации.

5. Избегайте потерь

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

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

«Точно так же для хранения переменного количества элементов, к которым не нужно обращаться по индексу, LinkedList может быть более производительным. Это не связано с какими-либо накладными расходами на управление памятью.

6. Резюме