This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

preface

See this question, at a glance, such a simple question, why asked. In fact, on second thought, yes, this is still a very confusing question. For starters, this is really easy to get lost in. Many people don’t understand.

So, let’s take a look at this problem and make an in-depth dissection of it!

Problem of repetition

Define a collection with an initial size of 10

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Add elements using the collection method

Arr. Add (5, 10)

So let’s see what happens

Where there is confusion, why would they report crossing the line? We have already initialized the collection size to 10, add method, add index to 5, less than 10.

It is estimated that beginners have been overwhelmed, so let’s take a detailed look at what is going on.

Problem resolution

So first of all, let’s look at the collection add method, how is it defined

/**
 * Inserts the specified element at the specified position in this
 * list. Shifts the element currently at that position (if any) and
 * any subsequent elements to the right (adds one to their indices).
 *
 * @param index index at which the specified element is to be inserted
 * @param element element to be inserted
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}
Copy the code

Method, which does provide two arguments, the index location, and the element value.

By looking at the comments, we can see that the specified element is inserted at the specified position in this list. Moves the element currently in that position (if any) and any subsequent elements right (add one to its index).

/**
 * A version of rangeCheck used by add and addAll.
 */
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
Copy the code

Observation method rangeCheckForAdd

As we can see, this method evaluates the comparison between index and size

/**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial
 */
private int size;
Copy the code

So, when we see the previous exception screenshot, the Size is 0, that’s why it came, we seem to have initialized the Size.

The problem, it seems, is initialization. So let’s see what we’re doing when we customize collections.

/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); }}Copy the code

InitialCapacity = initialCapacity; initialCapacity = initialCapacity;

The problem is clear. We have confused the concepts of Size and Capacity.

The problem summary

Size is the number of elements that the collection contains

Capacity defines the number of elements that a collection can contain

Beginners, need to observe the implementation of the source code more carefully.