Java容器類原始碼-Vector的最全的原始碼分析(一)
一、概述
我們都知道,在Java的Collections包含了List和Set,而List裡面有ArrayList、LinkedList、還有Vector,對於很多Java初學者來說,前面兩個比較常用,ArrayList查詢效率比較高(底層是陣列實現),而LinkedList的增刪效率比較高(底層是雙向連結串列實現)。那麼Vector是什麼呢?它和ArrayList、LinkedList一樣,支援有序可重複地存放單列資料。它底層實現和ArrayList類似,都是陣列實現,因此在技術面試中, 面試官比較喜歡拿ArrayList和Vector進行比較。儘管Vector在Java1.2之後進行了優化更新,但是Java官方還是推薦在不需要考慮執行緒安全的情況下,優先使用ArrayList。
二、Vector和ArrayList的對比
那麼,Vector和ArrayList既然都是陣列實現,它們到底有什麼區別呢?通過對比它們的原始碼,可以總結出以下兩個區別:
(1) Vector的所有方法都是有synchronized關鍵字的,即每一個方法都是同步的,所以在使用起來效率會非常低,但是保證了執行緒安全;而ArrayList的全部方法都是非同步的,所以相對Vector的效率會更高,所以它是執行緒不安全的。
(2) ArrayList在每次擴容時都是增加當前容量的1.5倍,而Vector在擴容時都是增加當前容量的兩倍。
綜上,Vector在增刪改查等API上的實現都是和ArrayList類似甚至是相同的,所以如果你看了ArrayList的原始碼,那麼Vector的原始碼你肯定是一下就看懂了,如果你還沒看ArrayList的原始碼,請移步到《Java容器類原始碼-ArrayList的最全的原始碼分析》。所以在不需要考慮執行緒安全時,Java官方推薦我們使用ArrayList,那麼,如果執行緒不安全時呢?我們應該怎麼選擇?我們都知道,Java在Collections類中給我們提供了同步ArrayList的方法public static <T> List<T> synchronizedList(List<T> list)。它可以幫助我們實現同步ArrayList,但是你通過看synchronizedList的實現就會知道,它其實是建立了一個新的類叫做SynchronizedList,它其實只是對ArrayList的增刪改查等常用方法加了synchronized欄位,所以它的效率其實和Vector是一樣的,這個也在我們後面講到的subList()原始碼裡面得到印證,不信,我們在程式碼裡面測試一下:
/** * 測試使用Collections.synchronizedList呼叫增、刪、改三個API操作50000個數據,求100次的平均時間 * */ public class QTest { public static void main(String[] args) { long totalTime = 0; for (int i = 0; i < 100; i++) { totalTime += new QTest().getTime(); } System.out.println("Collections.synchronizedList() 平均耗時:" + (totalTime / 100)); } public long getTime() { List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>()); long startTime = System.currentTimeMillis(); for (int i = 0; i < 50000; i++) { list.add(i * 10); // 增加 } for (int i = 0; i < 50000; i++) { // 修改 list.set(i, i); } for (int i = 0; i < list.size(); i++) { // 刪除 list.remove(i); } long endTime = System.currentTimeMillis(); System.out.println("Collections.synchronizedList()消耗時間:" + (endTime - startTime)); return endTime - startTime; } } /** * 測試使用Vector呼叫增、刪、改三個API操作50000個數據,求100次的平均時間 * */ public class PTest { public static void main(String[] args) { long totalTime = 0; for (int i = 0; i < 100; i++) { totalTime += new QTest().getTime(); } System.out.println("vector 平均耗時:" + (totalTime / 100)); } public long getTime() { Vector<Integer> vector = new Vector<>(); long nStartTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { vector.add(i * 10); // 增加 } for (int i = 0; i < 100000; i++) { // 修改 vector.set(i, i); } for (int i = 0; i < vector.size(); i++) { // 刪除 vector.remove(i); } long nEndTime = System.currentTimeMillis(); System.out.println("vector消耗時間:" + (nEndTime - nStartTime)); return nEndTime - nStartTime; } }
這兩段程式碼其實就是對同步的ArrayList進行增、刪、改50000條資料,並重復100次,求平均時間。通過執行,在我的電腦(每臺電腦的執行速度不一樣)裡Collections.synchronizedList的100次平均消耗時間是:129ms,而Vector的100次平均消耗時間是:130ms。在需要考慮執行緒安全時,你是用Vector和Collections.synchronizedList初始化的ArrayList大概效率是差不多的。所以,Vector也並非毫無用武之地,那麼這次我們就一起探究一下Vector的原始碼。
---------------------
每天都在分享文章,也每天都有人想要我出來給大家分享下怎麼去學習Java。大家都知道,我們是學Java全棧的,大家就肯定以為我有全套的Java系統教程。沒錯,我是有Java全套系統教程,進扣裙【47】974【9726】所示,進群的時候記得表明自己想要學習什麼,不要用小號,這樣小編才好給你們發定向資源,今天小編就免費送!~
“我們相信人人都可以成為一個程式設計師,現在開始,找個師兄,帶你入門,學習的路上不再迷茫。這裡是ja+va修真院,初學者轉行到網際網路行業的聚集地。"