深刻理解JAVA集合------List體系

List體系以下:node

 

類與接口說明:編程

   一、Collection:高度抽象出來的集合、定義某一類集合所具備的基本的方法、標準。數組

   二、Iterable:標識性接口、要求子類提供獲取Iterator方法、而且要實現Iterator具備的幾個方法。安全

   三、Iterator:迭代器、用於迭代Collection中元素、要求子類必須實現獲取Iterator的方法。數據結構

   四、List:以隊列的形式存儲、操做元素、定義了這種形式的集合所具備的基本方法、以及方法的定義。要求List實現類集合中每一個元素都有索引、索引值從0開始。多線程

   五、AbstractCollection:Collection的實現類、要求須要實現Collection接口的類都必須從它繼承、目的是用於簡化編程。併發

   六、AbstractList:繼承AbstractCollection、實現List接口中定義方法、目的也是簡化編程、而且其內部提供了獲取Iterator、ListIterator的方法。工具

   七、AbstractSequencedList:繼承AbstractList、使得List支持有序隊列、好比鏈表形式存儲操做元素。性能

   八、ArrayList:繼承AbstractList、以動態數組的形式存儲、操做元素。this

   九、LinkedList:繼承AbstractSequencedList、實現Deque、List接口、以雙向鏈表的形式存儲、操做元素。

   十、Vector:繼承AbstractList、以動態數組的形式存儲、操做元素、線程安全。

 

ArrayList 與 LinkedList對比:

   相同點:

      1)都直接或者間接繼承了AbstractList,因此都支持以索引的方式操做元素;

      2)都不須要擔憂容量問題,ArrayList是經過動態數組的形式來保存數據的,當容量不足會自動擴容。(注:ArrayList初始化容量爲10,擴容代碼以下:

 /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

      3)都是線程不安全的、通常用於單線程的環境下、要想在併發的環境下使用可使用Collections工具類包裝。

   不一樣點:

      1)ArrayList是經過動態數據保存數據的,LinkedList是經過雙向鏈表保存數據的;

      2)相對與ArrayList而言,LinkedList繼承了AbstractSequentialList,而AbstractSequentialList繼承了AbstractList,因此使得LinkedList不只保留了以索引操做元素的功能,同時實現了雙向鏈表所具備的功能;

      3)對集合中元素進行不一樣的操做效率不一樣、LinkedList善於刪除、添加元素、ArrayList善於查找元素。本質就是不一樣數據結構之間差別。

ArrayList 與 Vector的對比:

   相同點:

      1)都是繼承AbstractList、擁有相同的方法的定義;

      2)內部都是以動態數組來存儲、操做元素的、而且均可以自動擴容。

   不一樣點:

      1)線程安全:ArrayList是線程不安全的、適用於單線程的環境下、Vector是線程安全的、使用與多線程的環境下;

      2)構造方法:Vector有四個構造方法、比ArrayList多一個能夠指定每次擴容多少的構造方法;

      3)擴容問題:每當動態數組元素達到上線時、ArrayList擴容爲1.5倍,Vector爲2倍;Vector擴容代碼以下:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

      4)效率問題:由於Vector要同步方法、這個是要消耗資源的、因此效率會比較低下;

數組、ArrayList、LinkedList、Vector操做元素對比:

   實現機制  查詢  寫  迭代操做
 數組  連續內存區域保存元素數據  1  不支持  不支持
 ArrayList  以數組保存數據  2  2  2
 LinkedList  以鏈表保存數據  4  1  1
 Vector  以數組保存數據  3  3  3

 

 

 

 

 

    數組犧牲長度變化,直接在內存在開闢固定空間保存數據,因此查詢速率最快,可是由於size大小固定,因此不支持寫操做。

    a)ArrayList查詢的速率比LinkedList的快,二者都是經過索引去查找元素,ArrayList是直接經過index定位到元素位置,而LinkedList是經過二分法肯定元素位置範圍,再逐個查找,直到找到該元素爲止。相比ArrayList     來講LinkedList更耗時,更耗費資源。二者查詢元素源碼以下:

/**
*ArrayList經過索引查詢元素
**/ 
public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

 E elementData(int index) {
        return (E) elementData[index];
    }

/**
*LinkedList經過索引查詢元素
**/ 
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

可是ArrayList的寫操做效率明顯低於LinkedList,緣由以下:

對於指定index處的插入、刪除、ArrayList和LinkedList都是先經過索引查找到指定位置、而後進行下一步的插入刪除操做、上面咱們知道LinkedList是先經過二分法查找index範圍再肯定index具體位置、可是ArrayList是直接定位到index處、爲何LinkedList反而快?依然經過源碼找緣由。

對比上面代碼能夠看出來ArrayList每當插入一個元素時、都會調用System.arraycopy()將指定位置後面的全部元素後移一位、從新構造一個數組、這是比較消耗資源的、而LinkedList是直接改變index先後元素的上一個節點和下一個節點的引用、而不須要動其餘的東西、因此效率很高。

 

ArrayList、Vector都是繼承與AbstractList、而且在類結構上沒有多少差別、可是由於Vector要同步方法、因此在性能上不如ArrayList、從源碼也能夠看出Vector許多方法都是使用關鍵字synchronized修飾的。

相關文章
相關標籤/搜索