В чем преимущество явной установки емкости ArrayList

В java ArrayList у нас есть конструктор -

ArrayList(int capacity)

и два методы -

void ensureCapacity(int minCapacity)

void trimToSize()

Рассмотрим пример кода:

ArrayList<String> arrayList3 = new ArrayList<>(5);
System.out.println(arrayList3.size());

arrayList3.add("Zebra");
arrayList3.add("Giraffe");
arrayList3.add("Bison");

System.out.println(arrayList3);
System.out.println(arrayList3.size());

arrayList3.add("Rhino");
arrayList3.add("Hippo");
arrayList3.add("Elephant");
arrayList3.add("Antelope");

System.out.println(arrayList3);
System.out.println(arrayList3.size());

Выход:

0
[Zebra, Giraffe, Bison]
3
[Zebra, Giraffe, Bison, Rhino, Hippo, Elephant, Antelope]
7

Здесь я не вижу, как установка начальной емкости влияет на выполнение программы. ArrayList — это гибкий список, который меняет размер по запросу. Итак, каково значение явной установки вместимость?

И в случае, если я хочу явно установить вместимость, есть ли способ просмотреть текущий вместимость? Так как int size() здесь явно не применимо.

Из документов класса: «Приложение может увеличить емкость экземпляра ArrayList перед добавлением большого количества элементов с помощью операции sureCapacity. Это может уменьшить объем добавочного перераспределения».

tobias_k 17.05.2022 17:22

@tobias_k, ты имеешь в виду экономию времени?

Payel Senapati 17.05.2022 17:24

Посмотрите здесь baeldung.com/….

Faeem azaz Bhanej 17.05.2022 17:27

Не уверен, как это реализовано, но я предполагаю, что когда емкость превышена, он выделяет новый резервный массив большего (двойного?) Размера и копирует все элементы (их ссылки) в новый массив. Если вы заранее знаете емкость, вы можете пропустить этот шаг (возможно, несколько раз). Кроме того, это может сэкономить память, не выделяя слишком много «лишнего» пространства, но опять же, здесь только догадки...

tobias_k 17.05.2022 17:27

Есть ли способ узнать текущую установленную мощность? @тобиас_к

Payel Senapati 17.05.2022 17:28

@tobias_k Вы абсолютно правы. Я читал эту вещь однажды в статье

Faeem azaz Bhanej 17.05.2022 17:29

@FaeemazazBhanej, как узнать текущую установленную емкость, а не размер в ArrayList?

Payel Senapati 17.05.2022 17:35

Хм, вроде только у Вектор был capacity(), но до ArrayList не довели. Хотя это внутренняя информация, которая на самом деле бесполезна для общего программирования, поэтому она делает API более чистым.

Kayaman 17.05.2022 17:53

@PayelSenapati how to know the currently set capacity and not size in ArrayList? Вызовите trimToSize(), затем вместимость == размеру. Хорошо, это немного банально, но я думаю, что идея в том, что пользователь обычно не должен об этом беспокоиться.

markspace 17.05.2022 18:02
Основы программирования на Java
Основы программирования на Java
Java - это высокоуровневый объектно-ориентированный язык программирования, основанный на классах.
Концепции JavaScript, которые вы должны знать как JS программист!
Концепции JavaScript, которые вы должны знать как JS программист!
JavaScript (Js) - это язык программирования, объединяющий HTML и CSS с одной из основных технологий Всемирной паутины. Более 97% веб-сайтов используют...
1
9
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ArrayList как реализация структуры данных Динамический массив.

Он изменяет размер, когда его базовый массив заполняется (т. е. текущий индекс списка превышает последний допустимый индекс базового массива).

Когда это произойдет, метод add() (или addAll) внутри вызовет метод grow(). Что удвоит вместимость. т.е. он создаст новый массив с length в два раза больше, чем предыдущий length плюс количество новые элементы, которые не вписываются в текущий размер.

Рост имеет стоимость На), поскольку все ранее добавленные элементы необходимо скопировать в новый массив.

Напоминание: когда изменение размера не требуется, новый элемент будет добавлен в постоянное времяО(1).

Конструктор без аргументов создает ArrayList емкостью 10.

Если вы ожидаете, что вновь созданный элемент ArrayList в конечном итоге будет содержать, скажем, элементы 50,000, имеет смысл использовать перегруженный конструктор для обеспечения начальная мощность элемента 50,000, чтобы повысить производительность, избегая ненужного изменения размера.

Кроме того, для этого вы можете использовать метод ensureCapacity(), который доступен в классе ArrayList (но не в интерфейсе List, поскольку понятие вместимость неприменимо к LinkedList, который не поддерживается массивом).

is there any method to view the current capacity

Нет, нет. Это называется инкапсуляция. ArrayList, StringBuilder, HashMap и т. д. поддерживаются простым массивом, но они не позволяют напрямую взаимодействовать со своим базовым массивом.

Но если у вас есть случай, когда массив изначально увеличивается в размере, а затем удаляется много элементов, и вы хотите освободить незанятое место в куче, вы можете использовать метод trimToSize():

Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.

Но его нужно использовать с осторожностью, потому что это может привести к циклическому росту и обрезке, что приведет к снижению производительности.

Примечание, что не нужно беспокоиться о количестве незанятого пространства, если список среднего размера или если вы не ожидаете, скажем, 80% данных, которые будут удалены за один раз. т.е. даже если список огромен, но 50% его элементов удаляется, и вы применяете к нему trimToSize(), он восстановит свою прежнюю емкость со следующим добавленным элементом - это сценарий непрерывного роста и сокращения списка, который будет работать плохо.

Как возможный вариант, если у вас есть случай, когда большая часть данных можно удалить из списка, вместо использования trimToSize() вы можете отфильтровать элементы, которые должны быть сохранены, поместить их в новый список и разыменовать предыдущий.

Чтобы использовать ensureCapacity() и trimToSize() человек, который не написал код, должен пройти ранний код, чтобы узнать изначально установленную мощность. Это неудобное дело, отнимающее много времени. Такой метод, как int capacity(), безусловно, был бы очень удобным. Я отмечаю это как недостаток Java

Payel Senapati 17.05.2022 21:26

Просто чтобы быть чрезмерно педантичным, он не создает «новый массив с длиной в два раза больше, чем предыдущая длина», поскольку «вдвое больше» будет в три раза больше. Как вы сказали ранее, он в два раза больше, или, говоря «больше», «в один раз больше».

GreyBeardedGeek 18.05.2022 02:56

@GreyBeardedGeek Спасибо, что указали на эту оплошность. Надеюсь, теперь он выглядит лучше.

Alexander Ivanchenko 18.05.2022 03:51

@PayelSenapati Вам не нужно беспокоиться об относительно небольших списках (что мало, зависит от вашей среды), но с точки зрения чистой логики, чем меньше ArrayList, тем быстрее он растет. Из-за этого не представляется разумным пытаться его обрезать. Также обратите внимание, что случаи массового удаления должны затрагивать гораздо больше, чем 50% элемента, иначе применение trimToSize() будет бесплодным. В качестве возможного решения вы можете отфильтровать все элементы, которые должны быть сохранены, и сохранить их в новом списке.

Alexander Ivanchenko 18.05.2022 04:34

Другие вопросы по теме