ArrayList簡(jiǎn)介
- ArrayList內(nèi)部是以動(dòng)態(tài)數(shù)組存放數(shù)據(jù)的,所謂動(dòng)態(tài)數(shù)組,不是數(shù)組本身可以改變長(zhǎng)度,而是保留原有數(shù)組引用的情況下創(chuàng)建一個(gè)新的數(shù)組,使用體驗(yàn)就像是可自動(dòng)擴(kuò)容的數(shù)組。
- ArrayList內(nèi)部是數(shù)組,支持?jǐn)?shù)組的所有特性,通過(guò)索引支持隨機(jī)訪問(wèn),所以訪問(wèn)效率高,但是插入和刪除效率低下。
- ArrayList實(shí)現(xiàn)了AbstractList抽象類、List接口、所以其更具有了AbstractList和List的功能,AbstractList內(nèi)部已經(jīng)實(shí)現(xiàn)了獲取Iterator和ListIterator的方法,所以ArrayList只需關(guān)心對(duì)數(shù)組操作的方法即List接口的實(shí)現(xiàn)。
- ArrayList實(shí)現(xiàn)了RandomAccess接口、此接口只有聲明、沒(méi)有方法體、表示ArrayList支持隨機(jī)訪問(wèn)。
- ArrayList實(shí)現(xiàn)了Cloneable接口、此接口只有聲明、沒(méi)有方法體、表示ArrayList支持克隆。
- ArrayList實(shí)現(xiàn)了Serializable接口、此接口只有聲明、沒(méi)有方法體、表示ArrayList支持序列化、即可以將ArrayList以流的形式通過(guò)ObjectInputStream/ObjectOutputStream來(lái)寫/讀。
ArrayList的擴(kuò)容
- 初始容量為10:使用無(wú)參構(gòu)造的創(chuàng)建ArrayList的時(shí)候默認(rèn)容量為10。
- 擴(kuò)容規(guī)則:每次add元素(單個(gè)或者一組)的時(shí)候,都要先檢查容量是否夠用。如果發(fā)現(xiàn)容量不夠,就設(shè)置新容量為原有容量1.5倍+1,如果新容量還不夠用,就直接把新容量設(shè)置為能盛放當(dāng)前元素量的值。然后就是使用Arrays.copyOf()方法把原數(shù)據(jù)copy到新數(shù)組中去。由此可見,使用ArrayList盡量明確使用上限,自動(dòng)擴(kuò)容雖好,但是效率不高。
- 為什么是1.5倍:跟源代碼中的算法有關(guān)“oldCapacity + (oldCapacity >> 1);”
- Arrays.copyOf():最終使用的是操作系統(tǒng)的api進(jìn)行數(shù)組復(fù)制,效率比我們手寫代碼要高。
- 擴(kuò)容限制:擴(kuò)容并非是無(wú)限制的,有內(nèi)存限制,虛擬機(jī)限制。
手寫ArrayList幫助理解
public class MyArrayList<T> implements Iterable<T> {
private T[] theItems;
private int theSize;
private static final int DEAULT_CAPACITY=10;
public MyArrayList(){
theSize=0;
ensureCapacity(DEAULT_CAPACITY);
}
public void add(T data){
if(size()==theItems.length){
ensureCapacity(size()*2+1);
}
theItems[size()]=data;
theSize++;
}
public void add(int index,T data){
if(size()==theItems.length){
ensureCapacity(size()*2+1);
}
for(int i=theSize;i>index;i--){
theItems[i]=theItems[i-1];
}
theItems[index]=data;
theSize++;
}
public T get(int index){
if(index<0|index>=size()){
throw new IndexOutOfBoundsException("index error");
}
return theItems[index];
}
public T remove(int index){
T removeData=get(index);
for(int i=index;i<size()-1;i++){
theItems[i]=theItems[i+1];
}
theSize--;
return removeData;
}
public int size(){
return theSize;
}
private void ensureCapacity(int newCapacity){
if(theSize>newCapacity){
return;
}
T[] old=theItems;
theItems= (T[]) new Object[newCapacity];
for(int i=0;i<size();i++){
theItems[i]=old[i];
}
}
@Override
public Iterator<T> iterator() {
return null;
}
@Override
public void forEach(Consumer<? super T> action) {
}
@Override
public Spliterator<T> spliterator() {
return null;
}
}
參考文章:
Java容器之ArrayList