publicstaticvoidmain(String[] args){
List<String> list =newArrayList<String>(10);
list.add(2,"1");
System.out.println(list.get(0));}
嗯?不知道!👀眼睛看题,看我脸干啥?好好好,告诉你吧,这样会报错!至于为什么,回家看看书吧。
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index:2, Size:0
at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:665)
at java.util.ArrayList.add(ArrayList.java:477)
at org.itstack.interview.test.ApiTest.main(ApiTest.java:13)
Process finished with exit code 1
List<String> list =newArrayList<String>(10);publicArrayList(){this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/**
* 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
*/publicArrayList(int initialCapacity){if(initialCapacity >0){this.elementData =newObject[initialCapacity];}elseif(initialCapacity ==0){this.elementData = EMPTY_ELEMENTDATA;}else{thrownewIllegalArgumentException("Illegal Capacity: "+
initialCapacity);}}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/publicbooleanadd(E e){ensureCapacityInternal(size +1);// Increments modCount!!
elementData[size++]= e;returntrue;}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index:2, Size:0
at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:665)
at java.util.ArrayList.add(ArrayList.java:477)
at org.itstack.interview.test.ApiTest.main(ApiTest.java:14)
其实,一段报错提示,为什么呢?我们翻开下源码学习下。
2.3.1 容量验证
publicvoidadd(int index, E element){rangeCheckForAdd(index);...}privatevoidrangeCheckForAdd(int index){if(index > size || index <0)thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}
publicvoidadd(int index, E element){...// 判断是否需要扩容以及扩容操作ensureCapacityInternal(size +1);// 数据拷贝迁移,把待插入位置空出来
System.arraycopy(elementData, index, elementData, index +1,
size - index);// 数据插入操作
elementData[index]= element;
size++;}
这部分源码的主要核心是在,System.arraycopy,上面我们已经演示过相应的操作方式。
这里只是设定了指定位置的迁移,可以把上面的案例代码复制下来做测试验证。
实践:
List<String> list =newArrayList<String>(Collections.nCopies(9,"a"));
System.out.println("初始化:"+ list);
list.add(2,"b");
System.out.println("插入后:"+ list);
测试结果:
初始化:[a, a, a, a, a, a, a, a, a]
插入后:[a, a,1, a, a, a, a, a, a, a]
Process finished with exit code 0
指定位置已经插入元素1,后面的数据向后迁移完成。
3. 删除
有了指定位置插入元素的经验,理解删除的过长就比较容易了,如下图;
这里我们结合着代码:
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;// clear to let GC do its workreturn oldValue;}