ArrayList&LinkedList性能比拼

學習過數據結構的同窗都會有這樣的一個印象,ArrayList的底層是由數組操做的,它的操做本質來說是對封裝數組的操做,而LinkedList的底層則是由鏈表實現的。java

而數組因爲其地址是連續的,因此在知道了數組第一個元素的地址,再調用其它的地址,則尋址速度會在o(1)的時間裏完成,而鏈表則須要進行表的遍歷,找到符合條件的再返回,於是對於讀來說,ArrayList的速度比較快。數組

但若是進入到了添加和刪除的階段,那可就要另說了,由於數組是要緊湊着的,因此在刪除了數組中某一位置的元素,它後面的元素會依次向前移動一個單元格,保證數組不會出現空的狀況。因此會有大量的數據移動的過程,所以若是一個集合寫入和刪除操做比較頻繁,則選用LinkedList集合。數據結構

咱們爲了驗證以上的結論,能夠寫下以下的代碼:dom

public class ListVisitPerformanceCompare {
    public static void main(String[] args) {
        int totalNum = 10000;
        List<Integer> arrList = new ArrayList<>();
        List<Integer> linkList = new LinkedList<>();
        int[] idxArr = new int[totalNum];
        Random random = new Random();
        for (int i = 0; i < totalNum; i++) {
            int randInt = random.nextInt();
            idxArr[i] = random.nextInt(totalNum);
            arrList.add(randInt);
            linkList.add(randInt);
        }
        calGetTimeCost(arrList, idxArr);
        calGetTimeCost(linkList, idxArr);
    }

    private static void calGetTimeCost(List<Integer> arrList, int[] idxArr) {
        int len = idxArr.length;
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < len; i++) {
            arrList.get(idxArr[i]);
        }
        System.out.println("在集合 :" + arrList.getClass().getName() + "下隨機抽取" + len + "條數據,耗時:"
                + (System.currentTimeMillis() - startTime) + "ms");
    }
}

如上,咱們在容量爲10000的ArrayList和LinkedList集合分別隨機訪問10000次集合中的元素,獲得的結果以下:性能

在集合 :java.util.ArrayList下隨機抽取10000條數據,耗時:1ms
在集合 :java.util.LinkedList下隨機抽取10000條數據,耗時:69ms

咱們接下來驗證第二個結論,一樣,寫下以下的代碼:學習

public class ListOperationPerformanceCompare {
    public static void main(String[] args) {
        int initialSize = 1000;
        // 操做多少次
        int operationTime = 100000;

        List<Integer> arrList = new ArrayList<>();
        List<Integer> linkList = new LinkedList<>();
        Random random = new Random();

        // 初始化集合
        for (int i = 0; i < initialSize; i++) {
            int randInt = random.nextInt();
            arrList.add(randInt);
            linkList.add(randInt);
        }
        int tmpSize = initialSize;
        Operation[] operationArr = new Operation[operationTime];
        for (int i = 0; i < operationTime; i++) {
            int num = random.nextInt();
            int operation = num & 1;
            tmpSize += operation == 0 ? -1 : 1;
            // 拒絕指針異常
            if (tmpSize <= 0) {
                tmpSize = 1;
                operation = 1;
            }
            int idx = random.nextInt(tmpSize);
            operationArr[i] = new Operation(operation, idx, num);
        }
        calOperationCostTime(arrList, operationArr);
        calOperationCostTime(linkList, operationArr);
    }

    static void calOperationCostTime(List<Integer> list, Operation[] operationArr) {
        int len = operationArr.length;
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < len; i++) {
            switch (operationArr[i].operation) {
                case 0:
                    list.remove(operationArr[i].idx);
                    // list.remove(0);
                    break;
                case 1:
                    list.add(operationArr[i].idx, operationArr[i].num);
                    // list.add(0, operationArr[i].num);
                    break;
                default:
            }
        }
        System.out.println("在集合 :" + list.getClass().getName() + "下隨機增刪" + len + "次,耗時:"
                + (System.currentTimeMillis() - startTime) + "ms");
    }

    static class Operation {
        public Operation(int operation, int idx, int num) {
            this.operation = operation;
            this.idx = idx;
            this.num = num;
        }

        /**
         * 0:刪除 1:添加
         */
        int operation;

        /**
         * 位置
         */
        int idx;

        /**
         * 要插入的數字(若是是插入操做)
         */
        int num;
    }
}

咱們運行的結果是:this

在集合 :java.util.ArrayList下隨機增刪100000次,耗時:43ms
在集合 :java.util.LinkedList下隨機增刪100000次,耗時:126ms

爲何會出現這樣的狀況呢?指針

由於鏈表在進行刪除的時候雖然只須要移動鏈表指針的地址,但要找到在哪裏進行操做倒是一個很是耗時的操做,因此LinkedList的性能主要消耗在了尋找地址上了。code

從上面的例子咱們能夠看出,若是沒有特殊的狀況,選取集合的時候優先選取ArrayList。orm

相關文章
相關標籤/搜索