Я думаю, что метод trimToSize() в Java ArrayList не нужен. Насколько я понимаю:

Возьмем массив целых чисел:

int[] a = new int[10]; //This allocates ten free slots proactively.

Основным преимуществом ArrayList является то, что он может создавать массивы динамически во время выполнения, что позволяет экономить память. Теперь код ArrayList<Integer> arl = new ArrayList<Integer>(10); не будет назначать десять свободных слотов заранее; вместо этого он добавляет слоты только тогда, когда есть данные для хранения.

Теперь в спецификации Java сказано, что trimToSize() удалит неиспользуемое пространство из ArrayList, но, как я понимаю, в ArrayList не будет неиспользуемого пространства, потому что пространство создается только тогда, когда данные доступны, а когда данные доступны, неиспользуемое или свободного места будет ноль.

3
user1613360 3 Июн 2014 в 06:18

2 ответа

Лучший ответ

Ваше понимание неверно. Если вы создаете new ArrayList<Integer>(10), он создаст массив целых чисел размера 10, заполненный нулями внутри ArrayList в качестве ядра своей модели данных. Он заполнит некоторые или все слоты в зависимости от количества элементов и увеличит размер базового массива, если количество элементов превысит его возможное количество. Актуален метод trimToSize().

9
Hovercraft Full Of Eels 3 Июн 2014 в 02:20

Избыточный: нет. Полезный? Только в очень специфических ситуациях.

Что вы должны знать, так это то, что ArrayList увеличивает массив поддержки, когда он заполнен определенным соотношением элементов.

[то, что здесь стояло раньше, использовалось для Map, а не ArrayList]

ArrayList внутренне будет проверять каждый раз, когда добавляется элемент, следует ли изменять размер массива поддержки:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
}

private void ensureCapacityInternal(int minCapacity) {
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

Я не учел некоторые вещи, которые в основном были пограничными проверками. Итак, как видите: когда заканчивается место для добавления элемента, он создает новый массив в 1,5 раза больше предыдущего и добавляет в него все элементы. При начальном значении 10 элементов, после этого сразу же будет 15.

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

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

5
Jeroen Vannevel 3 Июн 2014 в 02:40