ArrayList的基本存储数据结构为数组
ArrayList 的add源码为:
public boolean add(E e){
ensureCapacityInternal(size +1);
elementData[size++]==e;
return true;
}
``在当前存储结构足够存储的时候,就直接把数组的size+1项的元素设为e即可。
其中的ensureCapacityInternal函数的源码为:
private void ensureCapacityInternal(int minCapacity){
if(elementData == EMPTY_ELEMENTDATA){
minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
``其中DEFULT_CAPACITY为10,即当你初始化ArrayList的时候最小初始大小为10,ensureExplicitCapacity函数的源码为:
private void ensureExplicitCapacity(int minCapacity){
modCount++;
if(minCapacity - elementData.length>0){
grow(minCapacity);
}
}
``这里判断了当前需要的size即minCapacity是否大于element的长度,若供小于需,则需要扩容。
grow()的源码为:
private void grow(int minCapacity){
int oldCapacity = elementData.length;
int newCapacity = oldCapacity+(oldCapacity>>1);
if(newCapacity - minCapacity<0)
newCapacity=minCapacity;
if(newCapacity-MAX_ARRAY_SIZE>0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyof(element,newCapacity);
}
这里就是先确定扩容后的ArrayList数组的大小,然后在调用coryof,拷贝到新的数组中后赋给elementData。从这段源码可以知道ArrayList的存储数量是有限的,通过hugeCapacity函数得知为Integer的MAX_VALUE,想想也是,当存储超过Integer的最大值时,数组的下标无法表示的啊。
以上讲完ArrayList的add函数后,我们看看remove的源码:
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;
return oldValue;
}
从以上源码可以得知,当删除元素时是非常耗时的,他会把要删除的元素的后面所有元素都向前复制(移动)一位,然后ArrayList的size-1,之前位置的value置为null,方便GC回收。
我们再看get的源码:
public E get(int index){
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset+index);
}
就是检查的下标是否越界,然后拿出来从初始存储位置加上index的元素值。
public E set(int index,E e){
rangeCheck(index);
checkForComodification();
E oldValue = Array.this.elementData(offset + index);
ArrayList.this.elementData[offset +index]=e;
return oldValue;
}
这段源码比较容易理解,也是先检查了是否数组越界。
contains的源码为:
public boolean contains(Object o){
return indexOf(o)>=0;
}
public int indexOf(Object o){
if(o==null){
for(int i=0;i if(elementData[i]==null) return i; } }else { for(int i=0;i if(o.equals(elementData[i)) return i; } } return -1; } 通过以上源码得知,检查是否包含某元素的方式就是遍历所有元素,效率不高。indexOf返回的是第一个等于该值的下标,还有lastIndexOf返回的是最后一个等于该值的下标。 还有clone的源码: public Object clone(){ try{ ArrayList v.elementData = Arrays.copyof(elementData,size); v.modCount = 0; }catch(CloneNotSupportedException e){ throw new InternalError(); } } 由此可见ArrayList的clone的克隆只是简单的克隆一下指向,并不会把所有的值再复制一份。