Java源碼分析——ArrayList

之前已經(jīng)分析了HashMap的源碼,知道HashMap的內(nèi)部數(shù)據(jù)結(jié)構(gòu)是數(shù)組+鏈表+紅黑樹。相對于HashMap,ArrayList的內(nèi)部實(shí)現(xiàn)方法和操作都簡單的多。之前在看《Thinking In Java》的時(shí)候已經(jīng)知道:ArrayList內(nèi)部是用數(shù)組實(shí)現(xiàn)的,所以對于隨機(jī)查詢,效率會很高。但是對于在數(shù)組中間插入數(shù)據(jù),和刪除中間元素時(shí),會導(dǎo)致后續(xù)元素的移動(dòng)。

jkd源碼版本為1.8.0_05

類的結(jié)構(gòu)

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

繼承了AbstractList抽象類,其中實(shí)現(xiàn)了List需要的絕大多數(shù)公共方法。實(shí)現(xiàn)List, Cloneable, Serializable接口。還有一個(gè)RandomAccess接口,這是一個(gè)空的接口,代表這個(gè)類支持快速隨機(jī)訪問。

構(gòu)造函數(shù)

//使用一個(gè)指定的初始化容量構(gòu)造ArrayList
public ArrayList(int initialCapacity) {
  super();
  if (initialCapacity < 0)
    throw new IllegalArgumentException("Illegal Capacity: "+
                                       initialCapacity);
  this.elementData = new Object[initialCapacity];
}
//初始化一個(gè)空數(shù)組
public ArrayList() {
  super();
  this.elementData = EMPTY_ELEMENTDATA;
}
//接受一個(gè)Collection類型的參數(shù),轉(zhuǎn)化為數(shù)組之后進(jìn)行復(fù)制
public ArrayList(Collection<? extends E> c) {
  elementData = c.toArray();
  size = elementData.length;
  // c.toArray might (incorrectly) not return Object[] (see 6260652)
  if (elementData.getClass() != Object[].class)
    elementData = Arrays.copyOf(elementData, size, Object[].class);
}

成員字段

//初始化的默認(rèn)容量
private static final int DEFAULT_CAPACITY = 10;
//共享空數(shù)組
private static final Object[] EMPTY_ELEMENTDATA = {};
//ArrayList中的元素?cái)?shù)組
transient Object[] elementData; // non-private to simplify nested class access
//ArrayList中含有元素的個(gè)數(shù)
private int size;

這里對“共享空數(shù)組” Shared empty array instance 不是很理解。

關(guān)鍵方法

添加—add()
/**
 * 將特定的元素添加到數(shù)組的尾部
 */
public boolean add(E e) {
  //檢查空間大小
  ensureCapacityInternal(size + 1);  // Increments modCount!!
  elementData[size++] = e;
  return true;
}

private void ensureCapacityInternal(int minCapacity) {
  //如果當(dāng)前的數(shù)據(jù)元素是空數(shù)組,那么需要的容量和默認(rèn)容量的最大值作為需要的容量
  if (elementData == EMPTY_ELEMENTDATA) {
    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  }
  //檢查是否需要擴(kuò)容
  ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
  modCount++;

  // overflow-conscious code 如果需要的容量大于當(dāng)前數(shù)組的長度,進(jìn)行一次擴(kuò)容
  if (minCapacity - elementData.length > 0)
    grow(minCapacity);
}

private void grow(int minCapacity) {
  // overflow-conscious code
  int oldCapacity = elementData.length;
  //擴(kuò)容1.5倍
  int newCapacity = oldCapacity + (oldCapacity >> 1);
  if (newCapacity - minCapacity < 0)
    newCapacity = minCapacity;
  if (newCapacity - MAX_ARRAY_SIZE > 0)
    newCapacity = hugeCapacity(minCapacity);
  // minCapacity is usually close to size, so this is a win:
  //然后將數(shù)組元素放到新的數(shù)組中
  elementData = Arrays.copyOf(elementData, newCapacity);
}

/**
 *插入一個(gè)指定的元素到特定的位置。將右邊的所有元素向右移動(dòng)一位
 */
public void add(int index, E element) {
  //針對與添加元素,檢查是否越界。
  rangeCheckForAdd(index);
  //檢查是否需要擴(kuò)容
  ensureCapacityInternal(size + 1);  // Increments modCount!!
  //將index---size的元素,拷貝到index+1---size+1的位置上
  System.arraycopy(elementData, index, elementData, index + 1,size - index);
  //插入數(shù)據(jù)
  elementData[index] = element;
  size++;
}
private void rangeCheckForAdd(int index) {
  if (index > size || index < 0)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

刪除—remove()
//刪除指定位置的元素,將右邊的所有元素左移一位。
public E remove(int index) {
  //index不能超過size
  rangeCheck(index);

  modCount++;
  E oldValue = elementData(index);
  //需要移動(dòng)的元素個(gè)數(shù)
  int numMoved = size - index - 1;
  if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,numMoved);
  //復(fù)制之后將size--,然后把最后一位賦值null
  elementData[--size] = null; // clear to let GC do its work

  return oldValue;
}

private void rangeCheck(int index) {
  if (index >= size)
    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}


public boolean remove(Object o) {
  if (o == null) {
    //遍歷,刪除第一個(gè)為null的元素
    for (int index = 0; index < size; index++)
      if (elementData[index] == null) {
        fastRemove(index);
        return true;
      }
  } else {
    //遍歷,刪除第一個(gè)和o相等的元素,用equals來判斷
    for (int index = 0; index < size; index++)
      if (o.equals(elementData[index])) {
        fastRemove(index);
        return true;
      }
  }
  return false;
}

private void fastRemove(int index) {
  modCount++;
  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 work
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容