ArrayList: how does the size increase?

后端 未结 19 773
既然无缘
既然无缘 2020-11-29 18:11

I have a basic question on Java ArrayList.

When ArrayList is declared and initialized using the default constructor, memory space for 10 el

相关标签:
19条回答
  • 2020-11-29 18:31

    Typically, the memory for ArrayList type containers is increased by doubling it. Thus, if you initially had space for 10 items and you added 10, the eleventh item will be added to a new (internal) array of 20 items. The reason for this is that the incremental cost of adding items is reduced from O(n^2) if the array had been incremented in fixed size increments to a nice O(n) when doubling the size each time the internal array is full.

    0 讨论(0)
  • 2020-11-29 18:32

    The default size of the arraylist is 10. When we add the 11th ....arraylist increases the size (n*2). The values stored in old arraylist are copied into the new arraylist whose size is 20.

    0 讨论(0)
  • 2020-11-29 18:33

    Lets look at this code (jdk1.8)

    @Test
        public void testArraySize() throws Exception {
            List<String> list = new ArrayList<>();
            list.add("ds");
            list.add("cx");
            list.add("cx");
            list.add("ww");
            list.add("ds");
            list.add("cx");
            list.add("cx");
            list.add("ww");
            list.add("ds");
            list.add("cx");
            list.add("last");
        }
    

    1)Put break point on the line when "last" is inserted

    2)Go to the add method of ArrayList You will see

    ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
    

    3) Go to ensureCapacityInternal method this method call ensureExplicitCapacity

    4)

    private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
    
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
                return true;
    

    In our example minCapacity is equal to 11 11-10 > 0 therefore You need grow method

    5)

    private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    

    Lets describe each step:

    1) oldCapacity = 10 because we didn't put this param when ArrayList was init ,therefore it will use default capacity(10)

    2) int newCapacity = oldCapacity + (oldCapacity >> 1); Here newCapacity is equal to oldCapacity plus oldCapacity with right shift by one (oldCapacity is 10 this is the binary representation 00001010 moving one bit to right we will get 00000101 which is 5 in decimal therefore newCapacity is 10 + 5 = 15)

    3)

    if (newCapacity - minCapacity < 0)
                    newCapacity = minCapacity;
    

    For example your init capacity is 1, when you add the second element into arrayList newCapacity will be equal to 1(oldCapacity) + 0 (moved to right by one bit) = 1 In this case newCapacity is less than minCapacity and elementData(array object inside arrayList) can't hold new element therefore newCapacity is equal to minCapacity

    4)

    if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
    

    Check if array size reach MAX_ARRAY_SIZE (which is Integer.MAX - 8) Why the maximum array size of ArrayList is Integer.MAX_VALUE - 8?

    5) Finally it copy old values to the newArray with length 15

    0 讨论(0)
  • 2020-11-29 18:36

    It will depend on the implementation, but from the Sun Java 6 source code:

    int newCapacity = (oldCapacity * 3)/2 + 1;
    

    That's in the ensureCapacity method. Other JDK implementations may vary.

    0 讨论(0)
  • 2020-11-29 18:38

    When ArrayList is declared and initialized using the default constructor, memory space for 10 elements is created.

    NO. When ArrayList is initialized, memory allocation is made for an empty array. Memory allocation for default capacity (10) is made only upon addition of first element to ArrayList.

     /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
     * DEFAULT_CAPACITY when the first element is added.
     */
    private transient Object[] elementData;
    

    P.S. Don't have enough reputation to comment on question, so I am putting this as an answer as nobody pointed out this incorrect assumption earlier.

    0 讨论(0)
  • 2020-11-29 18:40

    A new array is created and the contents of the old one are copied over. That's all you know at the API level. Quoting from the docs (my emphasis):

    Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.

    In terms of how it actually happens with a specific implementation of ArrayList (such as Sun's), in their case you can see the gory details in the source. But of course, relying on the details of a specific implementation isn't usually a good idea...

    0 讨论(0)
提交回复
热议问题