程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java聚集框架ArrayList源碼剖析(一)

Java聚集框架ArrayList源碼剖析(一)

編輯:關於JAVA

Java聚集框架ArrayList源碼剖析(一)。本站提示廣大學習愛好者:(Java聚集框架ArrayList源碼剖析(一))文章只能為提供參考,不一定能成為您想要的結果。以下是Java聚集框架ArrayList源碼剖析(一)正文


ArrayList底層保護的是一個靜態數組,每一個ArrayList實例都有一個容量。該容量是指用來存儲列表元素的數組的年夜小。它老是至多等於列表的年夜小。跟著向 ArrayList 中赓續添加元素,其容量也主動增加。

 ArrayList不是同步的(也就是說不是線程平安的),假如多個線程同時拜訪一個ArrayList實例,而個中至多一個線程從構造上修正了列表,那末它必需堅持內部同步,在多線程情況下,可使用Collections.synchronizedList辦法聲明一個線程平安的ArrayList,例如:
List arraylist = Collections.synchronizedList(new ArrayList());
上面經由過程ArrayList的源碼來剖析其道理。
1、ArrayList的結構辦法:ArrayList供給了三種分歧的結構辦法
1) ArrayList(),結構一個初始容量為 10 的空列表。
2) ArrayList(int initialCapacity),結構一個具有指定初始容量的空列表。
3) ArrayList(Collection<? extends E> c),結構一個包括指定 collection 的元素的列表,這些元素是依照該 collection 的迭代器前往它們的次序分列的。

源碼以下: 

private transient Object[] elementData;

public ArrayList(int initialCapacity) {

  super();

  if (initialCapacity < 0)

    throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);

  this.elementData = new Object[initialCapacity]; //生成一個長度為10的Object類型的數組

 }

 

 

 public ArrayList() {

  this(10); //挪用ArrayList(int i)

 }<br><br>

 public ArrayList(Collection<? extends E> c) {

    elementData = c.toArray();  //前往包括此 collection 中一切元素的數組

  size = elementData.length;

  // c.toArray might (incorrectly) not return Object[] (see 6260652)

  if (elementData.getClass() != Object[].class)

   elementData = Arrays.copyOf(elementData, size, Object[].class); //復制指定的數組,前往包括雷同元素和長度的Object類型的數組

 }

當采取不帶參數的結構辦法ArrayList()生成一個聚集對象時,實際上是在底層挪用ArrayList(int initialCapacity)這一結構辦法臨盆一個長度為10的Object類型的數組。當采取帶有聚集類型參數的結構辦法時,在底層生成一個包括雷同的元素和長度的Object類型的數組。 

2、add辦法:ArrayList供給了兩種添加元素的add辦法
1) add(E e),將指定的元素添加到此列表的尾部。
2) add(int index, E e),將指定的元素拔出此列表中的指定地位。向右挪動以後位於該地位的元素(假如有)和一切後續元素(將其索引加 1)private int size;

public boolean add(E e) {

  ensureCapacity(size + 1); // 擴展數組容量

  elementData[size++] = e;  //將元素e添加到下標為size的Object數組中,而且履行size++

  return true;

  }

 

 public void add(int index, E element) {

  if (index > size || index < 0) //假如指定要拔出的數組下標跨越數組容量或許指定的下標小於0,拋異常

    throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);

 

  ensureCapacity(size+1); // 擴展數組容量

  System.arraycopy(elementData, index, elementData, index + 1,size - index); //從指定源數組中復制一個數組,復制從指定的地位開端,到目的數組的指定地位停止。<br>                                          // elementData --- 源數組  index --- 源數組中的肇端地位  <br>                                          // elementData --- 目的數組 index+1 --- 目的數組中的肇端地位<br>                                          // size - index --- 要復制的數組元素的數目

  elementData[index] = element; //將要添加的元素放到指定的數組下標處

  size++;

  }

public void ensureCapacity(int minCapacity) {

  modCount++;

  int oldCapacity = elementData.length; //原數組的容量

  if (minCapacity > oldCapacity) {

    Object oldData[] = elementData;

    int newCapacity = (oldCapacity * 3)/2 + 1; //界說新數組的容量,為原數組容量的1.5倍+1

      if (newCapacity < minCapacity)

    newCapacity = minCapacity;

      // minCapacity is usually close to size, so this is a win:

      elementData = Arrays.copyOf(elementData, newCapacity); //復制指定的數組,前往新數組的容量為newCapacity

  }

  }

假如聚集中添加的元素跨越了10個,那末ArrayList底層會重生成一個數組,長度為原數組的1.5倍+1,並將原數組中的元素copy到新數組中,而且後續添加的元素都邑放在新數組中,當新數組的長度沒法包容新添加的元素時,反復該進程。這就是聚集添加元素的完成道理。

3、get辦法:
 1) get(int index),前往此列表中指定地位上的元素。

public E get(int index) {
  RangeCheck(index); //檢討傳入的指定下標能否正當
 
  return (E) elementData[index]; //前往數組下標為index的數組元素

  }
private void RangeCheck(int index) {
  if (index >= size) //假如傳入的下標年夜於或等於聚集的容量,拋異常
    throw new IndexOutOfBoundsException(
    "Index: "+index+", Size: "+size);

  }

4、remove辦法:
1) E remove(int index),移除此列表中指定地位上的元素。向左挪動一切後續元素(將其索引減 1)。
2) boolean remove(Object o),移除此列表中初次湧現的指定元素(假如存在)。假如列表不包括此元素,則列表不做修改,前往boolean值。 

public E remove(int index) {

  RangeCheck(index); //檢討指定的下標能否正當

 

  modCount++;

  E oldValue = (E) elementData[index]; //獲得指定下標的數組元素

 

  int numMoved = size - index - 1; //要挪動的元素個數

  if (numMoved > 0)

    System.arraycopy(elementData, index+1, elementData, index, numMoved); //挪動數組元素

  elementData[--size] = null; // Let gc do its work

 

  return oldValue;

  }

 

 public boolean remove(Object o) {

  if (o == null) { //假如傳入的參數為null

      for (int index = 0; index < size; index++)

    if (elementData[index] == null) { //移除初次湧現的null

      fastRemove(index);

      return true;

    }

  } else {

    for (int index = 0; index < size; index++)

    if (o.equals(elementData[index])) {

      fastRemove(index);

      return true;

    }

    }

  return false;

  }

 

private void fastRemove(int index) { //移除指定地位的元素,完成辦法相似remove(int i)

    modCount++;

    int numMoved = size - index - 1;

    if (numMoved > 0)

      System.arraycopy(elementData, index+1, elementData, index,

               numMoved);

    elementData[--size] = null; // Let gc do its work

  }

5、clone辦法:
1) Object clone(),前往此ArrayList實例的淺表正本(不復制這些元素自己) 。

public Object clone() {
  try {
    ArrayList<E> v = (ArrayList<E>) super.clone(); //挪用Object類的clone辦法前往一個ArrayList對象
    v.elementData = Arrays.copyOf(elementData, size); //復制目的數組
    v.modCount = 0;
    return v;

  } catch (CloneNotSupportedException e) {

    // this shouldn't happen, since we are Cloneable

    throw new InternalError();

  }

  }

以上經由過程對ArrayList部門症結源碼的剖析,曉得了ArrayList底層的完成道理,關於ArrayList源碼有以下幾點幾點總結:
 1) ArrayList 底層是基於數組來完成的,可以經由過程下尺度確的找到目的元素,是以查找的效力高;然則添加或刪除元素會觸及到年夜量元素的地位挪動,效力低。
 2) ArrayList供給了三種分歧的結構辦法,無參數的結構辦法默許在底層生成一個長度為10的Object類型的數組,當聚集中添加的元素個數年夜於10,數組會主動停止擴容,即生成一個新的數組,並將原數組的元素放到新數組中。
3) ensureCapacity辦法對數組停止擴容,它會生成一個新數組,長度是原數組的1.5倍+1,跟著向ArrayList中赓續添加元素,當數組長度沒法知足須要時,反復該進程。

以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved