好像這個問題是java筆試必有的一個問題,
一般大家都知道ArrayList和LinkedList的大致區別:
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針。
3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據。
由於sun的開源所以我們可以從代碼的角度來看他們兩個之間的區別;
先從構造函數說起
ArrayList 的默認構造函數
- publicArrayList(){
- this(10);
- }
這個10是什麼意思呢?再看看帶參數的構造函數就明白了
- publicArrayList(intinitialCapacity){
- super();
- if(initialCapacity<0)
- thrownewIllegalArgumentException("IllegalCapacity:"+
- initialCapacity);
- this.elementData=newObject[initialCapacity];
- }
原來是是爲ArrayList 分配了10個Object的數組存儲空間。
下面看看LinkedList的構造函數
- publicLinkedList(){
- header.next=header.previous=header;
- }
把鏈表的指針全部歸零,從上面的代碼可以看出LinkedList是個雙向的鏈表。
下面再來看看兩者的get 和add方法有上面區別
首先來看ArrayList add方法
- publicbooleanadd(Ee){
- ensureCapacity(size+1);//IncrementsmodCount!!
- elementData[size++]=e;
- returntrue;
- }
ensureCapacity 這個函數是什麼意思呢?看看就知道了
- publicvoidensureCapacity(intminCapacity){
- modCount++;
- intoldCapacity=elementData.length;
- if(minCapacity>oldCapacity){
- ObjectoldData[]=elementData;
- intnewCapacity=(oldCapacity*3)/2+1;
- if(newCapacity<minCapacity)
- newCapacity=minCapacity;
- //minCapacityisusuallyclosetosize,sothisisawin:
- elementData=Arrays.copyOf(elementData,newCapacity);
- }
- }
原來這個確保ArrayList 存儲空間自動增長的,看了代碼就知道原來ArrayList 初始化存儲空間的大小是10 然後以後以1.5+1的級數增長,在這個過程中先new 原來空間的1.5倍+1的新空間,然後把原來的數據拷貝到新的空間,所以說ArrayList 的添加數據的性能低於LinkedList,原來原因出在此處,那麼以後就可以在new ArrayList 的時候,根據實際數據的多少,大概的指定一下ArrayList 的初始化大小,這樣避免的多次數據拷貝,提高了系統性能,哈哈又學到了優化的一招。
接下來繼續看LinkedList的add方法
- publicbooleanadd(Ee){
- addBefore(e,header);
- returntrue;
- }
- privateEntry<E>addBefore(Ee,Entry<E>entry){
- Entry<E>newEntry=newEntry<E>(e,entry,entry.previous);
- newEntry.previous.next=newEntry;
- newEntry.next.previous=newEntry;
- size++;
- modCount++;
- returnnewEntry;
- }
就是雙向鏈表的添加操作,這是數據結構裏面的必修煉的功力之一,在添加的時候只要修改一下指針就ok了,沒有ArrayList 的增長空間拷貝數據的步驟,所以總體上看來在add的時候,LinkedList比ArrayList 快。
下面來看看ArrayList 的get方法
- publicEget(intindex){
- RangeCheck(index);
- return(E)elementData[index];
- }
RangeCheck 檢測訪問是否越界,然後根據索引下標直接返回值,果然快。
再來看看LinkedList的get方法
- publicEget(intindex){
- returnentry(index).element;
- }
- privateEntry<E>entry(intindex){
- if(index<0||index>=size)
- thrownewIndexOutOfBoundsException("Index:"+index+
- ",Size:"+size);
- Entry<E>e=header;
- if(index<(size>>1)){
- for(inti=0;i<=index;i++)
- e=e.next;
- }else{
- for(inti=size;i>index;i--)
- e=e.previous;
- }
- returne;
- }
一個一個去找是比較的慢,不過還是優化了,如果要找的數小於等於size的一半就從頭往後找,要是大於size的一半就從後往前找,LinkedList的get和ArrayList 比起來確實慢了很多。