前言:
在我們平常開發中難免會用到List集合來儲存資料,一般都會選擇ArrayList和LinkedList,以前只是大致知道ArrayList查詢效率高LinkedList插入刪除效率高,今天來實測一下。
先了解一下List
List列表類,順序儲存任何物件(順序不變),可重複。
List是繼承於Collection的介面,不能例項化。例項化可以用:
ArrayList(實現動態陣列),查詢快(隨意訪問或順序訪問),增刪慢。整體清空快,執行緒不同步(非執行緒安全)。陣列長度是可變的百分之五十延長
LinkedList(實現連結串列),查詢慢,增刪快。
Vector(實現動態陣列),都慢,被ArrayList替代。長度任意延長。執行緒安全(同步的類,函式都是synchronized)
Stack(實現堆疊)繼承於Vector,先進後出。
List基本操作
插入:add()
查詢:get()
刪除:remove(int index)
修改:set()
清空表:clear()
遍歷:用Iterator迭代器遍歷每個元素
ArrayList、LinkedList效能對比
為了很好的對比效率,直接寫個測試程式看下執行結果
模擬5w條資料指定插入第一位,然後查詢全部,迴圈刪除第一位,下面是測試ArrayList函式
private void testArrayList(){ ArrayList<String> list=new ArrayList<>(); int maxTestCount=50000; //測試新增 long start =System.currentTimeMillis(); for(int i =0;i<maxTestCount;i++){ list.add(0,String.valueOf(i)); } long end =System.currentTimeMillis(); Log.e(TAG,"ArrayList add cost time :"+(end-start)); //測試查詢 start =System.currentTimeMillis(); for(int i =0;i<maxTestCount;i++){ list.get(i); } end =System.currentTimeMillis(); Log.e(TAG,"ArrayList get cost time :"+(end-start)); //測試查詢 start =System.currentTimeMillis(); for(int i =maxTestCount;i>0;i--){ list.remove(0); } end =System.currentTimeMillis(); Log.e(TAG,"ArrayList remove cost time :"+(end-start)); }
測試LinkedList函式
private void testLinkedList(){ LinkedList<String> list=new LinkedList<>(); int maxTestCount=50000; //測試新增 long start =System.currentTimeMillis(); for(int i =0;i<maxTestCount;i++){ list.add(0,String.valueOf(i)); } long end =System.currentTimeMillis(); Log.e(TAG,"LinkedList add cost time :"+(end-start)); //測試查詢 start =System.currentTimeMillis(); for(int i =0;i<maxTestCount;i++){ list.get(i); } end =System.currentTimeMillis(); Log.e(TAG,"LinkedList get cost time :"+(end-start)); //測試查詢 start =System.currentTimeMillis(); for(int i =maxTestCount;i>0;i--){ list.remove(0); } end =System.currentTimeMillis(); Log.e(TAG,"LinkedList remove cost time :"+(end-start)); }
先後呼叫兩個函式,看下執行結果
通過上面的執行結果可以大致得出以下結論:
- ArrayList插入、刪除效率明顯低於LinkedList
- ArrayList查詢效率遠遠高於LinkedList
通過上面的結構是不是就可以認為插入刪除頻繁選擇LinkedList,追求查詢效率就選擇ArrayList呢,我們先來分析一下效率差別的原因,這個就跟資料結構有關係了,可以參考一些資料結構中連結串列的知識,arraylist 順序表,用陣列的方式實現。想想陣列要查詢那個元素只給出其下標即可,所以才說arraylist隨機訪問多的場景比較合適。但是如果刪除某個元素比如第 i 個元素,則要將 i 之後的元素都向前移一位以保證順序表的正確,增加也是一樣,要移動多個元素。要多次刪除增加的話是很低效的。而LinkedList是雙向連結串列,注意是連結串列。要查詢只能頭結點開始逐步查詢,沒有什麼給出下標即可直接查詢的便利,需要遍歷。但是,如果要增加後刪除一個元素的話,只需要改變其前後元素的指向即可,不需要像arraylist那樣整體移動,所以才說多用於增刪多的場合。
很感謝博友的建議與幫助,由於LinkedList查詢只能從頭結點開始逐步查詢的,可以使用 iterator 的方式,就不用每次都從頭結點開始訪問,因為它會快取當前結點的前後結點。實測查詢效率與ArrayList沒有太大差別
LinkedList<String> list = new LinkedList<>(); Iterator<String> it = list.iterator(); while(it.hasNext()){ String s = it.next(); }
List其他知識擴充套件
Vector 是向量佇列,和ArrayList一樣,它也是一個動態陣列,由陣列實現。但是ArrayList是非執行緒安全的,而Vector是執行緒安全的。
Stack 是棧,它繼承於Vector。它的特性是:先進後出(FILO, First In Last Out)。
總結:
通過執行結果和查閱資料基本上驗證了ArrayList和LinkedList效率問題,有助於在以後的開發中根據實際場景選擇合適的技術方案。