前言
看到这个问题的时候,一眼看去,这么简单的问题,为何会问。其实,转眼一想,是的,这个还是很具有迷惑性的问题。对于初学者,来说,这块确实容易迷失。很多人不理解。
那么,我们就来看看这个问题,对它进行一次深入的解剖!
问题复现
定义一个初始化大小为10的集合
ArrayList<Integer> arr=new ArrayList<Integer>(10);
使用集合方法进行添加元素
arr.add(5,10)
我们看一下结果
网络异常,图片无法展示
|
迷惑的地方出现了,为啥会报越界呢?我们明明已经初始化了集合的大小为10,add方法,添加的索引为5,还不到10。
估计初学者已经懵逼,我们就来详细看看咋回事。
问题解析
首先,我们来看集合的add方法,是怎么定义的
/** * 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++; }
方法,确实提供了两个参数,索引位置,元素值。
通过了解注释,我们可以看到,将指定的元素插入此列表中的指定位置。 将当前在该位置的元素(如果有)和任何后续元素右移(将其索引添加一个)
。
/** * A version of rangeCheck used by add and addAll. */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
观察方法rangeCheckForAdd
我们,可以了解到,该方法,判断的是index和size的比较
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
那么,我们看到之前异常截图,显示Size为0,这是为啥来,我们好像已经初始化了大小。
看来,问题,在于初始化。我们就来看看,我们自定义集合时,到底干了点什么。
/** * 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); } }
我们发现,初始化时,指定的是initialCapacity 初始化容量大小,看出来,并不是size大小。
问题明朗了,我们混淆了Size和Capacity的概念。
问题总结
size 是集合包含元素的数量
capacity 是定义集合能够包含元素的数量
初学者,需要更细心的观察源码的实现。