1. Обзор
Java позволяет нам создавать массивы фиксированного размера или использовать классы коллекций для выполнения аналогичной работы.
В этом уроке мы рассмотрим разницу между емкостью ArrayList
и размером массива.
Мы также рассмотрим примеры того, когда мы должны инициализировать ArrayList
с емкостью, а также преимущества и недостатки с точки зрения использования памяти.
2. Пример
Чтобы понять различия, давайте сначала попробуем оба варианта.
2.1. Размер массива
В java обязательно указывать размер массива при создании его нового экземпляра:
Integer[] array = new Integer[100];
System.out.println("Size of an array:" + array.length);
Здесь мы
создали целочисленный
массив размером 100, что привело к следующему выводу:
Размер массива:100
2.2. Емкость ArrayList
Теперь давайте создадим ArrayList
с начальной емкостью 100:
List<Integer> list = new ArrayList<>(100);
System.out.println("Size of the list is :" + list.size());
Размер списка: 0
Поскольку элементы еще не добавлены, размер равен нулю.
Теперь давайте добавим элемент в список и проверим его размер:
list.add(10);
System.out.println("Size of the list is :" + list.size());
Размер списка: 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. Резюме
В этой короткой статье мы увидели разницу между емкостью ArrayList
и размером массива. Мы также рассмотрели, когда мы должны инициализировать ArrayList
с емкостью и его преимуществами в отношении использования памяти и производительности.
Как всегда, код примера доступен на GitHub .