1. 程式人生 > >後端---Java中ArrayList和LinkedList區別和聯絡

後端---Java中ArrayList和LinkedList區別和聯絡

ArrayList和LinkedList的區別和聯絡

在一個多月之前,我曾寫過一篇部落格想要迅速簡潔的瞭解Java中所有的集合型別(List、Set、Map),然後一個月多後的我不得已又抱起《Java核心卷I 》仔細研讀,這是為什麼呢???

是因為“溫故而知新”還是因為“書讀百遍其義自顯”????

都不是!!!

因為我忘完了啊!

關於List和Set、Map的部落格,這裡給出連結 

 java中List、Set、Map之間的關係 https://blog.csdn.net/weixin_42504145/article/details/83119088

一.初識List 

首先我們從一副圖來看ArrayLIst和LinkedList的關係,很明顯他兩都實現了Java給出的List集合這個介面,但是我要說的是這個圖並不完善!!!

我們來看完善的定義: 

// lang java
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Queue<E>, Cloneable, Serializable

從繼承關係來看:

在這個引用中我們能看到的ArrayList集成了AbstractList這個父類,雖然Linkedlist繼承的是AbstractSequentialList這個父類,但這個父類仍繼承與AbstactList這個類,所有並沒有太大區別。 

從介面實現關係來看:

聯絡:無論是ArrayList和LinkedList都實現了List<E>、Cloneable、Serializable這三個介面。List介面會作為重點在下面詳細介紹,先來看另外兩個介面,Cloneable介面是一個標記介面,也就是沒有任何內容,這裡分析一下這個介面的用法,clone方法是在Object種定義的,而且是protected型的,只有實現了這個介面,才可以在該類的例項上呼叫clone方法,否則會丟擲CloneNotSupportException。Object中預設的實現是一個淺拷貝,也就是表面拷貝,如果需要實現深層次拷貝的話,必須對類中可變域生成新的例項。Serializable介面是一個物件序列化的介面,一個類只有實現了Serializable介面,它的物件才能被序列化。

區別:ArrayList實現了隨機訪問的介面RandomAccess,LinkedList實現了Quene的介面。ArrayList是基於動態陣列實現的list,而LinkedList是基於連結串列實現的list。所以,ArrayList擁有著陣列的特性,LinkedList擁有著連結串列的特性。

我們再來看List這個介面

 List集合是一個有序集合。元素會增加到容器中的特定位置。可以採用兩種方式訪問元素:使用迭代器訪問,或者使用一個整數索引來訪問。後一種方式稱為隨機訪問,因為這樣可以按任意順序訪問元素。與之不同的是,使用迭代器訪問時,必須順序地訪問元素。

List介面定義了多個用於隨即訪問的訪問:

void add(int index,E element)

void remove(int index)

E get(int index)

E set(int index,E element)

二. ArrayList和LinkedList

ArrayList 

ArrayList實現了List介面,它是以陣列的方式來實現的,陣列的特性是可以使用索引的方式來快速定位物件的位置,因此對於快速的隨機取得物件的需求,使用ArrayList實現執行效率上會比較好. 

ArrayListDemo:

public class ArrayListDemo {  
  
    public static void main(String[] args) {  
          
        List<String> userlist = new ArrayList<String>();  
        userlist.add("yulon");  
        userlist.add("xiaoyun");  
        userlist.add("羽龍共舞");  
        System.out.println("使用普通for迴圈:");  
        for(int i=0; i<userlist.size(); i++){  
            System.out.print(userlist.get(i)+" ");  
        }  
        System.out.println();  
        System.out.println();  
        System.out.println("使用Iterator迭代器:");  
        Iterator it = userlist.iterator();  
        while(it.hasNext()){  
            System.out.print(it.next()+" ");  
        }  
        System.out.println();  
        System.out.println();  
        System.out.println("使用增強for迴圈:");  
          
        for(String s : userlist){  
            System.out.print(s+" ");  
        }  
    }  
}  

這裡有三種輸出輸出List的方法,我們不建議用for迴圈輸出List,因為在下面的例子中用for迴圈輸出LinkedList會造成一個很嚴重的失誤,因為LinkedList底層是用連結串列實現的,如果使用get()方法獲取某個元素的值,LinkedList每次都會從頭開始遍歷極其損耗效能,我們建議用Iterator和for-each方法來輸出List集合,關於for-each方法內部也是生存成了一個Iterator物件,只不過在底層進行了封裝,我們看不見而已。如果關於Iterator不懂的可以參考我這篇部落格:

https://blog.csdn.net/weixin_42504145/article/details/85210723  Java中Iterator(迭代器)的用法及其背後機制的探究

LinkedList

LinkedList是採用連結串列的方式來實現List介面的,它本身有自己特定的方法,如: addFirst(),addLast(),getFirst(),removeFirst()等. 由於是採用連結串列實現的,因此在進行insert和remove動作時在效率上要比ArrayList要好得多!適合用來實現Stack(堆疊)與Queue(佇列),前者先進後出,後者是先進先出.

public class StringStack {  
    private LinkedList<String> linkedList   
    = new LinkedList<String>();  
  
    /** 
     * 將元素加入LinkedList容器 
     * (即插入到連結串列的第一個位置) 
     */  
    public void push(String name){  
        linkedList.addFirst(name);  
    }  
    /** 
     * 取出堆疊中最上面的元素 
     * (即取出連結串列linkedList的第一個元素) 
     * @return 
     */  
    public String getTop(){  
        return linkedList.getFirst();  
    }  
    /** 
     * 取出並刪除最上面的元素 
     * (即移出linkedList的第一個元素) 
     * @return 
     */  
    public String pop(){  
        return linkedList.removeFirst();  
    }  
    /** 
     * 獲取元素個數 
     * @return 
     */  
    public int size(){  
        return linkedList.size();  
    }  
      
    /** 
     * 判斷堆疊是否為空 
     * (即判斷 linkedList是否為空) 
     * @return 
     */  
    public boolean isEmpty(){  
        return linkedList.isEmpty();  
    }  
    //測試  
    public static void main(String[] args) {  
        StringStack stack = new StringStack();  
        stack.push("yulon");  
        stack.push("xiaoyun");  
        stack.push("羽龍共舞");  
        System.out.print("第一個元素是:\t");  
        System.out.println(stack.getTop());  
        System.out.println();  
        System.out.println("全部元素:");  
        while(!stack.isEmpty()){  
            System.out.println("\t"+stack.pop());  
        }  
    }  
}  

三.總結 

下面這些區別是我們都知道的:

   1.ArrayList是實現了基於動態陣列的資料結構,LinkedList基於連結串列的資料結構。 (LinkedList是雙向連結串列,有next也有previous)
     2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。 
     3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。 

我們再來自己總結總結ArrayList和LinkedList的區別: 

ArrayList和LinkedList在效能上各有優缺點,都有各自所適用的地方,總的說來可以描述如下: 

  • 對ArrayList和LinkedList而言,在列表末尾增加一個元素所花的開銷都是固定的。對ArrayList而言,主要是在內部陣列中增加一項,指向所新增的元素,偶爾可能會導致對陣列重新進行分配;而對LinkedList而言,這個開銷是統一的,分配一個內部Entry物件。
  • 在ArrayList的中間插入或刪除一個元素意味著這個列表中剩餘的元素都會被移動;而在LinkedList的中間插入或刪除一個元素的開銷是固定的。
  • LinkedList不支援高效的隨機元素訪問。
  • ArrayList的空間浪費主要體現在在list列表的結尾預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗相當的空間
  • 可以這樣說:當操作是在一列資料的後面新增資料而不是在前面或中間,並且需要隨機地訪問其中的元素時,使用ArrayList會提供比較好的效能;當你的操作是在一列資料的前面或中間新增或刪除資料,並且按照順序訪問其中的元素時,就應該使用LinkedList了。

 

 

 

參考連結:
https://blog.csdn.net/bjzhuhehe/article/details/72230559

https://www.cnblogs.com/Jacck/p/8034900.html

https://www.cnblogs.com/lxq0309/p/3655742.html