Vector, ArrayList, LinkedList分析

Vector分析:

主要特性:有序,可隨機訪問,可變長,可重複,線程安全等。 java

其結構圖: 數組

其基本屬性有: 安全

//存放元素的數組
protected Object[] elementData;
//元素個數
protected int elementCount;
//容量擴容指標,默認以2倍增加
protected int capacityIncrement;

從其構造函數中能夠看出,Vector默認容量爲10,capacityIncrement默認設爲0(<=0時就以2倍擴容): 併發

public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

public Vector() {
    this(10);
}

看幾個比較重要的方法,add(), remove(): 函數

add方法: 性能

public synchronized boolean add(E e) {
     modCount++;
     ensureCapacityHelper(elementCount + 1); //擴容檢測
     elementData[elementCount++] = e; //添加,改變引用
     return true;
 }

 private void ensureCapacityHelper(int minCapacity) {
      if (minCapacity - elementData.length > 0)
            grow(minCapacity);
 }

 private void grow(int minCapacity) {
      int oldCapacity = elementData.length;
      //默認2*oldCapacity, 
      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);//拷貝新數組
 }

remove方法,可見刪除操做要作複製操做: 測試

public synchronized E remove(int index) {
     modCount++;
     if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
     E oldValue = elementData(index); 
     int numMoved = elementCount - index - 1; //被刪除元素後面元素個數
     if (numMoved > 0)
         System.arraycopy(elementData, index+1, elementData, index,
                             numMoved); //將被刪除元素後面的元素往前挪
     elementData[--elementCount] = null; //這點很重要,讓gc可以回收無引用對象,防止"內存泄漏"
     return oldValue;
}

Vector實現是比較簡單明瞭的,其大部分方法都synchronized同步了,所以線程安全。 this

ArrayList分析:

其主要特性:有序,可隨機訪問,可變長,可重複,非線程安全等。 spa

其結構圖: 線程

其主要屬性:

//默認容量
private static final int DEFAULT_CAPACITY = 10;
//空標誌
private static final Object[] EMPTY_ELEMENTDATA = {};
//存放元素的數組
private transient Object[] elementData;
//元素個數
private int size;
其構造方法有(不能設置ArrayList的擴容機制):
public ArrayList(int initialCapacity) { //可指定初始容量
     super();
     if (initialCapacity < 0)
         throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
     this.elementData = new Object[initialCapacity];
}

public ArrayList() {
    super();
    this.elementData = EMPTY_ELEMENTDATA; //空數組
}

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}
看看其主要方法add, remove:

public boolean add(E e) {
     ensureCapacityInternal(size + 1);  //擴容
     elementData[size++] = e;
     return true;
}

private void ensureCapacityInternal(int minCapacity) {
     if (elementData == EMPTY_ELEMENTDATA) {
         minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
     }
     ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
     modCount++;
     // overflow-conscious code
     if (minCapacity - elementData.length > 0)
          grow(minCapacity);
}

private void grow(int minCapacity) {
     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1); //擴容爲原來的3/2倍
     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);
}

remove方法, 基本同上面Vector。

LinkedList分析:

其主要特性:可變長,可重複,不可隨機訪問,非線程安全等。

LinkedList不一樣於Vector,ArrayList(由數組實現),基於雙鏈表實現:

其結構圖:

其主要特性:可重複,不可隨機訪問,非線程安全。

其主要屬性:

//長度
transient int size = 0;
//頭
transient Node<E> first;
//尾
transient Node<E> last;

其將咱們的元素抽象爲Node類:

private static class Node<E> {
     E item; //元素對象
     Node<E> next; //後節點引用
     Node<E> prev; //前節點引用
     Node(Node<E> prev, E element, Node<E> next) {
         this.item = element;
         this.next = next;
         this.prev = prev;
     }
 }
仍是看看其主要方法, add,remove:

add方法:

public boolean add(E e) {
     linkLast(e); //接到尾上
     return true;
 }

 void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null) //空鏈表
          first = newNode;
    else
          l.next = newNode;
    size++;
    modCount++;
 }
remove方法, 主要由unlink方法實現:
E unlink(Node<E> x) {
   // assert x != null;
   final E element = x.item;
   final Node<E> next = x.next;
   final Node<E> prev = x.prev;

   if (prev == null) { //頭節點
       first = next;
   } else {
       prev.next = next;
       x.prev = null;
   }

   if (next == null) { //尾節點
       last = prev;
   } else {
       next.prev = prev;
       x.next = null;
   }

   x.item = null;
   size--;
   modCount++;
   return element;
}

上面就講了有關List集合的3個實現類,對於這三個類咱們該如何選取,就的根據具體狀況:

對於Vector和ArrayList, 須要同步時,則可用Vector, 或Collections.synchronizedList(),不需同步則用ArrayList, 對於這三種作了些性能測試:

  • Vector與SynchronizedList併發插入性能:5個線程,每一個線程插入100w元素,Vector要更快。
  • ArrayList與LinkedList插入性能: 當數據量比較小時,LinkedList更快(前者因爲複製操做耗時),當數據量比較大時(如>=50W), ArrayList更快(後者因爲遍歷操做耗時)。

不吝指正。

相關文章
相關標籤/搜索