Подтвердить что ты не робот

Уменьшается ли емкость ArrayList при удалении элементов?

ArrayList имеет емкость по умолчанию 10 объектов. Поскольку размер превышает 10 объектов, ArrayList будет внутренне увеличивать свою емкость. Уменьшается ли емкость, когда мы удаляем объект из ArrayList.

Если емкость ArrayList не уменьшается, это может привести к проблемам с производительностью?

4b9b3361

Ответ 1

Это не уменьшает это автоматически. Из документа

    public void trimToSize() 

Обрезает емкость этого экземпляра ArrayList как текущий текущий список. Приложение может использовать эту операцию для сведения к минимуму хранения экземпляра ArrayList.

Ответ 2

В arraylist существует несколько методов удаления, я буду использовать версию для удаления по индексу в качестве примера

 public E remove(int index) {

     rangeCheck(index);
     modCount++;
     E oldValue = elementData(index);

     int numMoved = size - index - 1;

     if (numMoved > 0)
           System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);

     elementData[--size] = null; // Let gc do its work


     return oldValue;

 }

Самое главное отметить, что новый массив никогда не создается в elementData, поэтому его размер не изменяется, копируются только элементы.

Если вам нужно уменьшить емкость списка массивов (который обычно не будет), используйте trimToSize()

Ответ 3

ArrayList предлагает метод trimToSize(), который "Обрезает емкость экземпляра ArrayList как текущий текущий список. Приложение может использовать эту операцию для сведения к минимуму хранения экземпляра ArrayList". См. http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#trimToSize().

Если какие-либо другие методы делают это действие молча, это будет зависеть от реализации, предоставляемой вашей JRE.

Ответ 4

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

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

My results are:
             Before:  125637904
         After Aloc:  126959888 -1321984
       After Insert:  126718560 241328
        After Clear:  126958496 -239936
         After trim:  126998432 -39936
      After nullify:  126998400 32

Что странно, и я не могу объяснить. Выделение списка уменьшало свободную память. Вставка в список увеличила свободную память (я этого не ожидал). Очистка списка уменьшает объем свободной памяти (???), обрезая список, снова освобождает свободную память (похоже, не очищает ее) и установка указателя списка на нуль должна верните нас туда, где мы начали, но это не так!

Мой код ниже:

package metcarob.com.dev.rubbish;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest {

    private static long outputMem(String pre, long last) {
        Runtime.getRuntime().gc();
        String pre2 = "                    " + pre;
        System.out.print(pre2.substring(pre2.length()-20) + "  ");

        long tv = Runtime.getRuntime().freeMemory();

        System.out.print(tv);

        if (last!=0) {
            System.out.print(" " + (last - tv));
        }

        System.out.println("");

        return tv;
    }

    public static void main(String[] args) {

        long lm = outputMem("Before:",0);

        ArrayList<String> lis = new ArrayList<String>();
        lis.ensureCapacity(10000);

        lm = outputMem("After Aloc:", lm);

        for (int c=0;c<10000;c++) {
            lis.add(new String("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"));
        };

        lm = outputMem("After Insert:", lm);

        lis.clear();

        lm = outputMem("After Clear:", lm);

        lis.trimToSize();

        lm = outputMem("After trim:", lm);

        lis = null;

        lm = outputMem("After nullify:", lm);

    }

}

Ответ 5

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

Это ваш случай использования, который определяет, как это влияет на производительность, воспринимаемую пользователем. Они работают на машине с низкой памятью? Мы говорим о больших, в основном статических массивах? Является ли массив постоянно меняющимся?

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

Ответ 6

do the the capacity decrease when we remove the object from ArrayList.

Ответ просто no. Если вы наблюдаете исходный код класса ArrayList, вы получите ответ.
Нет операции по уменьшению емкости метода ArrayList remove().