JAVA ArrayList的實現原理 及ArrayList的使用

一、 ArrayList概述:

ArrayList是基於數組實現的,是一個動態數組,其容量能自動增長,類似於C語言中的動態申請內存,動態增長內存。

ArrayList不是線程安全的,只能用在單線程環境下,多線程環境下可以考慮用Collections.synchronizedList(List l)函數返回一個線程安全的ArrayList類,也可以使用concurrent併發包下的CopyOnWriteArrayList類。



ArrayList實現了Serializable接口,因此它支持序列化,能夠通過序列化傳輸,實現了RandomAccess接口,支持快速隨機訪問,實際上就是通過下標序號進行快速訪問,實現了Cloneable接口,能被克隆。

每個ArrayList實例都有一個容量,該容量是指用來存儲列表元素的數組的大小。它總是至少等於列表的大小。隨着向ArrayList中不斷添加元素,其容量也自動增長。自動增長會帶來數據向新數組的重新拷貝,因此,如果可預知數據量的多少,可在構造ArrayList時指定其容量。在添加大量元素前,應用程序也可以使用ensureCapacity操作來增加ArrayList實例的容量,這可以減少遞增式再分配的數量。
注意,此實現不是同步的。如果多個線程同時訪問一個ArrayList實例,而其中至少一個線程從結構上修改了列表,那麼它必須保持外部同步。

二、 ArrayList的實現:

對於ArrayList而言,它實現List接口、底層使用數組保存所有元素。其操作基本上是對數組的操作。下面我們來分析ArrayList的源代碼:

1) 私有屬性:

ArrayList定義只定義類兩個私有屬性:

/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;

 /** 
  * The size of the ArrayList (the number of elements it contains). 
  * 
  * @serial 
  */  
 private int size;

很容易理解,elementData存儲ArrayList內的元素,size表示它包含的元素的數量。

有個關鍵字需要解釋:transient。

Java的serialization提供了一種持久化對象實例的機制。當持久化對象時,可能有一個特殊的對象數據成員,我們不想用serialization機制來保存它。爲了在一個特定對象的一個域上關閉serialization,可以在這個域前加上關鍵字transient。

有點抽象,看個例子應該能明白。

public class UserInfo implements Serializable {
private static final long serialVersionUID = 996890129747019948L;
private String name;
private transient String psw;

 public UserInfo(String name, String psw) {  
     this.name = name;  
     this.psw = psw;  
 }  

 public String toString() {  
     return "name=" + name + ", psw=" + psw;  
 }  

}

public class TestTransient {
public static void main(String[] args) {
UserInfo userInfo = new UserInfo(“張三”, “123456”);
System.out.println(userInfo);
try {
// 序列化,被設置爲transient的屬性沒有被序列化
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(
“UserInfo.out”));
o.writeObject(userInfo);
o.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
try {
// 重新讀取內容
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
“UserInfo.out”));
UserInfo readUserInfo = (UserInfo) in.readObject();
//讀取後psw的內容爲null
System.out.println(readUserInfo.toString());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

被標記爲transient的屬性在對象被序列化的時候不會被保存。

接着回到ArrayList的分析中……

2) 構造方法:
ArrayList提供了三種方式的構造器,可以構造一個默認初始容量爲10的空列表、構造一個指定初始容量的空列表以及構造一個包含指定collection的元素的列表,這些元素按照該collection的迭代器返回它們的順序排列的。

// ArrayList帶容量大小的構造函數。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException(“Illegal Capacity: “+
initialCapacity);
// 新建一個數組
this.elementData = new Object[initialCapacity];
}

// ArrayList無參構造函數。默認容量是10。    
public ArrayList() {    
    this(10);    
}    

// 創建一個包含collection的ArrayList    
public ArrayList(Collection<? extends E> c) {    
    elementData = c.toArray();    
    size = elementData.length;    
    if (elementData.getClass() != Object[].class)    
        elementData = Arrays.copyOf(elementData, size, Object[].class);    
}

3) 元素存儲:

ArrayList提供了set(int index, E element)、add(E e)、add(int index, E element)、addAll(Collection

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章