ArrayList源码分析

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 = (ArrayList) supper.clone();

          v.elementData = Arrays.copyof(elementData,size);

          v.modCount = 0;

     }catch(CloneNotSupportedException e){

          throw new InternalError();

     }

}

由此可见ArrayList的clone的克隆只是简单的克隆一下指向,并不会把所有的值再复制一份。

你可能感兴趣的:(ArrayList源码分析)