轉(zhuǎn)載:http://www.cnblogs.com/skywang12345/p/3308556.html
1罐韩、ArrayList介紹
ArrayList 是一個數(shù)組隊列污朽,相當于 動態(tài)數(shù)組散吵。與Java中的數(shù)組相比蟆肆,它的容量能動態(tài)增長矾睦。它繼承于AbstractList炎功,實現(xiàn)了List, RandomAccess, Cloneable, java.io.Serializable這些接口枚冗。
ArrayList 繼承了AbstractList蛇损,實現(xiàn)了List。它是一個數(shù)組隊列淤齐,提供了相關(guān)的添加股囊、刪除更啄、修改、遍歷等功能祭务。
ArrayList 實現(xiàn)了RandmoAccess接口内狗,即提供了隨機訪問功能。RandmoAccess是java中用來被List實現(xiàn)柳沙,為List提供快速訪問功能的喇勋。在ArrayList中,我們即可以通過元素的序號快速獲取元素對象偎行;這就是快速隨機訪問贰拿。
ArrayList 實現(xiàn)了Cloneable接口蛤袒,即覆蓋了函數(shù)clone()膨更,能被克隆妙真。
ArrayList 實現(xiàn)java.io.Serializable接口荚守,這意味著ArrayList支持序列化,能通過序列化去傳輸矗漾。
和Vector不同锈候,ArrayList中的操作不是線程安全的敞贡!所以,建議在單線程中才使用ArrayList誊役,而在多線程中可以選擇Vector或者CopyOnWriteArrayList。
2蛔垢、關(guān)鍵點
ArrayList包含了兩個重要的對象:elementData 和 size。
elementData 是"Object[]類型的數(shù)組"鹏漆,它保存了添加到ArrayList中的元素。實際上艺玲,elementData是個動態(tài)數(shù)組且改,我們能通過構(gòu)造函數(shù) ArrayList(int initialCapacity)來執(zhí)行它的初始容量為initialCapacity板驳;如果通過不含參數(shù)的構(gòu)造函數(shù)ArrayList()來創(chuàng)建ArrayList,則elementData的容量默認是10若治。elementData數(shù)組的大小會根據(jù)ArrayList容量的增長而動態(tài)的增長慨蓝,具體的增長方式,請參考源碼分析中的ensureCapacity()函數(shù)礼烈。
size 則是動態(tài)數(shù)組的實際大小。
transient Object[] elementData;
private int size;
3此熬、構(gòu)造函數(shù)
//帶指定初始容量的構(gòu)造函數(shù)
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//創(chuàng)建一個空的ArrayList, 默認容量為10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//創(chuàng)建一個包含Collection的ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
4、擴容函數(shù)
//增加容量為minCapacity
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//重點
grow(minCapacity);
}
擴容的核心募谎,grow()函數(shù):
//每次重新分配內(nèi)存時,新的容量為舊的1.5倍
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
////設(shè)置新的容量 = 舊容量*1.5
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果小于可允許的最小容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果大于可允許的最大容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//復(fù)制元素到新數(shù)組
//Arrays.copyOf函數(shù)返回一個新數(shù)組對象
elementData = Arrays.copyOf(elementData, newCapacity);
}
5数冬、clone()函數(shù)
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
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(e);
}
}
6、add()拐纱、get()、set()哥倔、remove()、clear()
6.1 add()操作
//添加元素
public boolean add(E e) {
//首先確定容量咆蒿,如果不夠,需要擴容
ensureCapacityInternal(size + 1); // Increments modCount!!
//在數(shù)組中下一個空位置上添加元素
elementData[size++] = e;
return true;
}
//指定位置index上添加元素蜡秽,原來位置元素并沒有消失,只是后移了一位,
//即將當前位于該位置的元素以及所有后續(xù)元素右移一個位置芽突。
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
//移動元素。
//將 elementData 中從index位置開始寞蚌、長度為size-index的元素,
//拷貝到從下標為index+1位置開始的新的elementData數(shù)組中挟秤。
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
6.2 get()操作
public E get(int index) {
//檢測有沒有數(shù)組越界
rangeCheck(index);
//返回index位置上的元素
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
6.3 set()操作
設(shè)置index上的元素為element,會覆蓋原來的值艘刚。
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
6.4 remove()操作
//去除指定位置index上的元素,該位置后所有元素前移一位
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; // clear to let GC do its work
return oldValue;
}
//移除在數(shù)組中首次出現(xiàn)的指定元素o,如果不存在返回false。
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
6.5 clear()操作
清空數(shù)組中的所有元素的引用。讓GC回收這些引用指向的對象岗喉。
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}