1.概述
关于Java集合的小抄中是这样描述的:
以数组实现。节约空间,但数组有容量限制。超出限制时会增加50%容量,用System.arraycopy()复制到新的数组,因此最好能给出数组大小的预估值。默认第一次插入元素时创建大小为10的数组。
按数组下标访问元素—get(i)/set(i,e)的性能很高,这是数组的基本优势。
直接在数组末尾加入元素—add(e)的性能也高,但如果按下标插入、删除元素—add(i,e),remove(i),remove(e),则要用System.arraycopy()来移动部分受影响的元素,性能就变差了,这是基本劣势。
ArrayList是一个相对来说比较简单的数据结构,最重要的一点就是它的自动扩容,可以认为就是我们常说的“动态数组”。
来看一段简单的代码:
ArrayListStringlist=newArrayListString();
list.add("语文:99");
list.add("数学:98");
list.add("英语:");
list.remove(0);
在执行这四条语句时,是这么变化的:
其中,add操作可以理解为直接将数组的内容置位,remove操作可以理解为删除index为0的节点,并将后面元素移到0处。
2.add函数
当我们在ArrayList中增加元素的时候,会使用add函数。他会将元素放到末尾。具体实现如下:
publicbooleanadd(Ee){
ensureCapacityInternal(size+1);//IncrementsmodCount!!
elementData[size++]=e;
returntrue;
}
我们可以看到他的实现其实最核心的内容就是ensureCapacityInternal。这个函数其实就是自动扩容机制的核心。我们依次来看一下他的具体实现
privatevoidensureCapacityInternal(intminCapacity){
if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA){
minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
privatevoidensureExplicitCapacity(intminCapacity){
modCount++;
//overflow-consciouscode
if(minCapacity-elementData.length0)
grow(minCapacity);
}
privatevoidgrow(intminCapacity){
//overflow-consciouscode
intoldCapacity=elementData.length;
//扩展为原来的1.5倍
intnewCapacity=oldCapacity+(oldCapacity1);
//如果扩为1.5倍还不满足需求,直接扩为需求值
if(newCapacity-minCapacity0)
newCapacity=minCapacity;
if(newCapacity-MAX_ARRAY_SIZE0)
newCapacity=hugeCapacity(minCapacity);
//minCapacityisusuallyclosetosize,sothisisawin:
elementData=Arrays.copyOf(elementData,newCapacity);
}
也就是说,当增加数据的时候,如果ArrayList的大小已经不满足需求时,那么就将数组变为原长度的1.5倍,之后的操作就是把老的数组拷到新的数组里面。例如,默认的数组大小是10,也就是说当我们add10个元素之后,再进行一次add时,就会发生自动扩容,数组长度由10变为了15具体情况如下所示:
3.set和get函数
Array的put和get函数就比较简单了,先做index检查,然后执行赋值或访问操作:
publicEset(intindex,Eelement){
rangeCheck(index);
EoldValue=elementData(index);
elementData[index]=element;
returnoldValue;
}
publicEget(intindex){
rangeCheck(index);
returnelementData(index);
}
4.remove函数
publicEremove(intindex){
rangeCheck(index);
modCount++;
EoldValue=elementData(index);
intnumMoved=size-index-1;
if(numMoved0)
//把后面的往前移
System.arraycopy(elementData,index+1,elementData,index,
numMoved);
//把最后的置null
elementData[--size]=null;//cleartoletGCdoitswork
returnoldValue;
}
注释很清楚:
Removestheelementatthespecifiedpositioninthislist.Shiftsanysubsequentelementstotheleft(subtractsonefromtheirindices).
北京白癜风治疗一般多少钱北京治疗白癜风医院有哪些