1. 程式人生 > 其它 >第一次例會記錄

第一次例會記錄

Vector可以實現可增長的物件陣列。與陣列一樣,它包含可以使用整數索引進行訪問的元件。不過,Vector的大小是可以增加或者減小的,以便適應建立Vector後進行新增或者刪除操作。

Vector實現List介面,繼承AbstractList類,所以我們可以將其看做佇列,支援相關的新增、刪除、修改、遍歷等功能。

Vector實現RandmoAccess介面,即提供了隨機訪問功能,提供提供快速訪問功能。在Vector我們可以直接訪問元素。

Vector 實現了Cloneable介面,支援clone()方法,可以被克隆。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector提供了四個建構函式:

/**
     * 構造一個空向量,使其內部資料陣列的大小為 10,其標準容量增量為零。
     */
     public Vector() {
            this(10);
     }
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 構造一個包含指定 collection 中的元素的向量,這些元素按其 collection 的迭代器返回元素的順序排列。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(Collection&lt;? <span style="color: #0000ff">extends</span> E&gt;<span style="color: #000000"> c) {
  elementData </span>=<span style="color: #000000"> c.toArray();
  elementCount </span>=<span style="color: #000000"> elementData.length;
  </span><span style="color: #008000">//</span><span style="color: #008000"> c.toArray might (incorrectly) not return Object[] (see 6260652)</span>
  <span style="color: #0000ff">if</span> (elementData.getClass() != Object[].<span style="color: #0000ff">class</span><span style="color: #000000">)
  elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, elementCount,
  Object[].</span><span style="color: #0000ff">class</span><span style="color: #000000">);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 使用指定的初始容量和等於零的容量增量構造一個空向量。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span><span style="color: #000000"> initialCapacity) {
  </span><span style="color: #0000ff">this</span>(initialCapacity, 0<span style="color: #000000">);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 使用指定的初始容量和容量增量構造一個空的向量。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span> initialCapacity, <span style="color: #0000ff">int</span><span style="color: #000000"> capacityIncrement) {
  </span><span style="color: #0000ff">super</span><span style="color: #000000">();
  </span><span style="color: #0000ff">if</span> (initialCapacity &lt; 0<span style="color: #000000">)
  </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> IllegalArgumentException(&quot;Illegal Capacity: &quot;+<span style="color: #000000">
  initialCapacity);
  </span><span style="color: #0000ff">this</span>.elementData = <span style="color: #0000ff">new</span><span style="color: #000000"> Object[initialCapacity];
  </span><span style="color: #0000ff">this</span>.capacityIncrement =<span style="color: #000000"> capacityIncrement;
  }</span></pre>

在成員變數方面,Vector提供了elementData , elementCount, capacityIncrement三個成員變數。其中

elementData :"Object[]型別的陣列",它儲存了Vector中的元素。按照Vector的設計elementData為一個動態陣列,可以隨著元素的增加而動態的增長,其具體的增加方式後面提到(ensureCapacity方法)。如果在初始化Vector時沒有指定容器大小,則使用預設大小為10.

elementCount:Vector 物件中的有效元件數。

capacityIncrement:向量的大小大於其容量時,容量自動增加的量。如果在建立Vector時,指定了capacityIncrement的大小;則,每次當Vector中動態陣列容量增加時>,增加的大小都是capacityIncrement。如果容量的增量小於等於零,則每次需要增大容量時,向量的容量將增大一倍。

同時Vector是執行緒安全的!

二、原始碼解析

對於原始碼的解析,LZ在這裡只就增加(add)刪除(remove)兩個方法進行講解。

2.1增加:add(E e)

add(E e):將指定元素新增到此向量的末尾。

public synchronized boolean add(E e) {
        modCount++;     
        ensureCapacityHelper(elementCount + 1);    //確認容器大小,如果操作容量則擴容操作
        elementData[elementCount++] = e;   //將e元素新增至末尾
        return true;
    }

這個方法相對而言比較簡單,具體過程就是先確認容器的大小,看是否需要進行擴容操作,然後將E元素新增到此向量的末尾。

private void ensureCapacityHelper(int minCapacity) {
        //如果
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 進行擴容操作
  * 如果此向量的當前容量小於minCapacity,則通過將其內部陣列替換為一個較大的陣列倆增加其容量。
  * 新資料陣列的大小姜維原來的大小 + capacityIncrement,
  * 除非 capacityIncrement 的值小於等於零,在後一種情況下,新的容量將為原來容量的兩倍,不過,如果此大小仍然小於 minCapacity,則新容量將為 minCapacity。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> grow(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
  </span><span style="color: #0000ff">int</span> oldCapacity = elementData.length; <span style="color: #008000">//</span><span style="color: #008000">當前容器大小</span>
  <span style="color: #008000">/*</span><span style="color: #008000">
  * 新容器大小
  * 若容量增量係數(capacityIncrement) &gt; 0,則將容器大小增加到capacityIncrement
  * 否則將容量增加一倍
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">int</span> newCapacity = oldCapacity + ((capacityIncrement &gt; 0) ?<span style="color: #000000">
  capacityIncrement : oldCapacity);
   
  </span><span style="color: #0000ff">if</span> (newCapacity - minCapacity &lt; 0<span style="color: #000000">)
  newCapacity </span>=<span style="color: #000000"> minCapacity;
   
  </span><span style="color: #0000ff">if</span> (newCapacity - MAX_ARRAY_SIZE &gt; 0<span style="color: #000000">)
  newCapacity </span>=<span style="color: #000000"> hugeCapacity(minCapacity);
   
  elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, newCapacity);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 判斷是否超出最大範圍
  * MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> hugeCapacity(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
  </span><span style="color: #0000ff">if</span> (minCapacity &lt; 0<span style="color: #000000">)
  </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> OutOfMemoryError();
  </span><span style="color: #0000ff">return</span> (minCapacity &gt; MAX_ARRAY_SIZE) ?<span style="color: #000000"> Integer.MAX_VALUE : MAX_ARRAY_SIZE;
  }</span></pre>

對於Vector整個的擴容過程,就是根據capacityIncrement確認擴容大小的,若capacityIncrement <= 0 則擴大一倍,否則擴大至capacityIncrement 。當然這個容量的最大範圍為Integer.MAX_VALUE即,2^32 - 1,所以Vector並不是可以無限擴充的。

2.2、remove(Object o)

/**
     * 從Vector容器中移除指定元素E
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }
  </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">boolean</span><span style="color: #000000"> removeElement(Object obj) {
  modCount</span>++<span style="color: #000000">;
  </span><span style="color: #0000ff">int</span> i = indexOf(obj); <span style="color: #008000">//</span><span style="color: #008000">計算obj在Vector容器中位置</span>
  <span style="color: #0000ff">if</span> (i &gt;= 0<span style="color: #000000">) {
  removeElementAt(i); </span><span style="color: #008000">//</span><span style="color: #008000">移除</span>
  <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
  }
  </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
  }
   
  </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> removeElementAt(<span style="color: #0000ff">int</span><span style="color: #000000"> index) {
  modCount</span>++; <span style="color: #008000">//</span><span style="color: #008000">修改次數+1</span>
  <span style="color: #0000ff">if</span> (index &gt;= elementCount) { <span style="color: #008000">//</span><span style="color: #008000">刪除位置大於容器有效大小</span>
  <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArrayIndexOutOfBoundsException(index + &quot; &gt;= &quot; +<span style="color: #000000"> elementCount);
  }
  </span><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (index &lt; 0) { <span style="color: #008000">//</span><span style="color: #008000">位置小於 &lt; 0</span>
  <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> ArrayIndexOutOfBoundsException(index);
  }
  </span><span style="color: #0000ff">int</span> j = elementCount - index - 1<span style="color: #000000">;
  </span><span style="color: #0000ff">if</span> (j &gt; 0<span style="color: #000000">) {
  </span><span style="color: #008000">//</span><span style="color: #008000">從指定源陣列中複製一個數組,複製從指定的位置開始,到目標陣列的指定位置結束。
  </span><span style="color: #008000">//</span><span style="color: #008000">也就是陣列元素從j位置往前移</span>
  System.arraycopy(elementData, index + 1<span style="color: #000000">, elementData, index, j);
  }
  elementCount</span>--; <span style="color: #008000">//</span><span style="color: #008000">容器中有效元件個數 - 1</span>
  elementData[elementCount] = <span style="color: #0000ff">null</span>; <span style="color: #008000">//</span><span style="color: #008000">將向量的末尾位置設定為null</span>
  }</pre>

因為Vector底層是使用陣列實現的,所以它的操作都是對陣列進行操作,只不過其是可以隨著元素的增加而動態的改變容量大小,其實現方法是是使用Arrays.copyOf方法將舊資料拷貝到一個新的大容量陣列中。Vector的整個內部實現都比較簡單,這裡就不在重述了。

三、Vector遍歷

Vector支援4種遍歷方式。

3.1、隨機訪問

因為Vector實現了RandmoAccess介面,可以通過下標來進行隨機訪問。

for(int i = 0 ; i < vec.size() ; i++){
        value = vec.get(i);
    }

3.2、迭代器

Iterator it = vec.iterator();
    while(it.hasNext()){
        value = it.next();
        //do something
    }

3.2、for迴圈

for(Integer value:vec){
        //do something
    }

3.4、Enumeration迴圈

Vector vec = new Vector<>();
    Enumeration enu = vec.elements();
    while (enu.hasMoreElements()) {
        value = (Integer)enu.nextElement();
    }

Vector可以實現可增長的物件陣列。與陣列一樣,它包含可以使用整數索引進行訪問的元件。不過,Vector的大小是可以增加或者減小的,以便適應建立Vector後進行新增或者刪除操作。

Vector實現List介面,繼承AbstractList類,所以我們可以將其看做佇列,支援相關的新增、刪除、修改、遍歷等功能。

Vector實現RandmoAccess介面,即提供了隨機訪問功能,提供提供快速訪問功能。在Vector我們可以直接訪問元素。

Vector 實現了Cloneable介面,支援clone()方法,可以被克隆。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector提供了四個建構函式:

/**
     * 構造一個空向量,使其內部資料陣列的大小為 10,其標準容量增量為零。
     */
     public Vector() {
            this(10);
     }
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 構造一個包含指定 collection 中的元素的向量,這些元素按其 collection 的迭代器返回元素的順序排列。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(Collection&lt;? <span style="color: #0000ff">extends</span> E&gt;<span style="color: #000000"> c) {
  elementData </span>=<span style="color: #000000"> c.toArray();
  elementCount </span>=<span style="color: #000000"> elementData.length;
  </span><span style="color: #008000">//</span><span style="color: #008000"> c.toArray might (incorrectly) not return Object[] (see 6260652)</span>
  <span style="color: #0000ff">if</span> (elementData.getClass() != Object[].<span style="color: #0000ff">class</span><span style="color: #000000">)
  elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, elementCount,
  Object[].</span><span style="color: #0000ff">class</span><span style="color: #000000">);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 使用指定的初始容量和等於零的容量增量構造一個空向量。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span><span style="color: #000000"> initialCapacity) {
  </span><span style="color: #0000ff">this</span>(initialCapacity, 0<span style="color: #000000">);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 使用指定的初始容量和容量增量構造一個空的向量。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">public</span> Vector(<span style="color: #0000ff">int</span> initialCapacity, <span style="color: #0000ff">int</span><span style="color: #000000"> capacityIncrement) {
  </span><span style="color: #0000ff">super</span><span style="color: #000000">();
  </span><span style="color: #0000ff">if</span> (initialCapacity &lt; 0<span style="color: #000000">)
  </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> IllegalArgumentException(&quot;Illegal Capacity: &quot;+<span style="color: #000000">
  initialCapacity);
  </span><span style="color: #0000ff">this</span>.elementData = <span style="color: #0000ff">new</span><span style="color: #000000"> Object[initialCapacity];
  </span><span style="color: #0000ff">this</span>.capacityIncrement =<span style="color: #000000"> capacityIncrement;
  }</span></pre>

在成員變數方面,Vector提供了elementData , elementCount, capacityIncrement三個成員變數。其中

elementData :"Object[]型別的陣列",它儲存了Vector中的元素。按照Vector的設計elementData為一個動態陣列,可以隨著元素的增加而動態的增長,其具體的增加方式後面提到(ensureCapacity方法)。如果在初始化Vector時沒有指定容器大小,則使用預設大小為10.

elementCount:Vector 物件中的有效元件數。

capacityIncrement:向量的大小大於其容量時,容量自動增加的量。如果在建立Vector時,指定了capacityIncrement的大小;則,每次當Vector中動態陣列容量增加時>,增加的大小都是capacityIncrement。如果容量的增量小於等於零,則每次需要增大容量時,向量的容量將增大一倍。

同時Vector是執行緒安全的!

二、原始碼解析

對於原始碼的解析,LZ在這裡只就增加(add)刪除(remove)兩個方法進行講解。

2.1增加:add(E e)

add(E e):將指定元素新增到此向量的末尾。

public synchronized boolean add(E e) {
        modCount++;     
        ensureCapacityHelper(elementCount + 1);    //確認容器大小,如果操作容量則擴容操作
        elementData[elementCount++] = e;   //將e元素新增至末尾
        return true;
    }

這個方法相對而言比較簡單,具體過程就是先確認容器的大小,看是否需要進行擴容操作,然後將E元素新增到此向量的末尾。

private void ensureCapacityHelper(int minCapacity) {
        //如果
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 進行擴容操作
  * 如果此向量的當前容量小於minCapacity,則通過將其內部陣列替換為一個較大的陣列倆增加其容量。
  * 新資料陣列的大小姜維原來的大小 + capacityIncrement,
  * 除非 capacityIncrement 的值小於等於零,在後一種情況下,新的容量將為原來容量的兩倍,不過,如果此大小仍然小於 minCapacity,則新容量將為 minCapacity。
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> grow(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
  </span><span style="color: #0000ff">int</span> oldCapacity = elementData.length; <span style="color: #008000">//</span><span style="color: #008000">當前容器大小</span>
  <span style="color: #008000">/*</span><span style="color: #008000">
  * 新容器大小
  * 若容量增量係數(capacityIncrement) &gt; 0,則將容器大小增加到capacityIncrement
  * 否則將容量增加一倍
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">int</span> newCapacity = oldCapacity + ((capacityIncrement &gt; 0) ?<span style="color: #000000">
  capacityIncrement : oldCapacity);
   
  </span><span style="color: #0000ff">if</span> (newCapacity - minCapacity &lt; 0<span style="color: #000000">)
  newCapacity </span>=<span style="color: #000000"> minCapacity;
   
  </span><span style="color: #0000ff">if</span> (newCapacity - MAX_ARRAY_SIZE &gt; 0<span style="color: #000000">)
  newCapacity </span>=<span style="color: #000000"> hugeCapacity(minCapacity);
   
  elementData </span>=<span style="color: #000000"> Arrays.copyOf(elementData, newCapacity);
  }
   
  </span><span style="color: #008000">/**</span><span style="color: #008000">
  * 判斷是否超出最大範圍
  * MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  </span><span style="color: #008000">*/</span>
  <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> hugeCapacity(<span style="color: #0000ff">int</span><span style="color: #000000"> minCapacity) {
  </span><span style="color: #0000ff">if</span> (minCapacity &lt; 0<span style="color: #000000">)
  </span><span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> OutOfMemoryError();
  </span><span style="color: #0000ff">return</span> (minCapacity &gt; MAX_ARRAY_SIZE) ?<span style="color: #000000"> Integer.MAX_VALUE : MAX_ARRAY_SIZE;
  }</span></pre>

對於Vector整個的擴容過程,就是根據capacityIncrement確認擴容大小的,若capacityIncrement <= 0 則擴大一倍,否則擴大至capacityIncrement 。當然這個容量的最大範圍為Integer.MAX_VALUE即,2^32 - 1,所以Vector並不是可以無限擴充的。

2.2、remove(Object o)

/**
     * 從Vector容器中移除指定元素E
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }
  </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">boolean</span><span style="color: #000000"> removeElement(Object obj) {
  modCount</span>++<span style="color: #000000">;
  </span><span style="color: #0000ff">int</span> i = indexOf(obj); <span style="color: #008000">//</span><span style="color: #008000">計算obj在Vector容器中位置</span>
  <span style="color: #0000ff">if</span> (i &gt;= 0<span style="color: #000000">) {
  removeElementAt(i); </span><span style="color: #008000">//</span><span style="color: #008000">移除</span>
  <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span><span style="color: #000000">;
  }
  </span><span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span><span style="color: #000000">;
  }
   
  </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> removeElementAt(<span style="color: #0000ff">int</span><span style="color: #000000"> index) {
  modCount</span>++; <span style="color: #008000">//</span><span style="color: #008000">修改次數+1</span>
  <span style="color: #0000ff">if</span> (index &gt;= elementCount) { <span style="color: #008000">//</span><span style="color: #008000">刪除位置大於容器有效大小</span>
  <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArrayIndexOutOfBoundsException(index + &quot; &gt;= &quot; +<span style="color: #000000"> elementCount);
  }
  </span><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (index &lt; 0) { <span style="color: #008000">//</span><span style="color: #008000">位置小於 &lt; 0</span>
  <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span><span style="color: #000000"> ArrayIndexOutOfBoundsException(index);
  }
  </span><span style="color: #0000ff">int</span> j = elementCount - index - 1<span style="color: #000000">;
  </span><span style="color: #0000ff">if</span> (j &gt; 0<span style="color: #000000">) {
  </span><span style="color: #008000">//</span><span style="color: #008000">從指定源陣列中複製一個數組,複製從指定的位置開始,到目標陣列的指定位置結束。
  </span><span style="color: #008000">//</span><span style="color: #008000">也就是陣列元素從j位置往前移</span>
  System.arraycopy(elementData, index + 1<span style="color: #000000">, elementData, index, j);
  }
  elementCount</span>--; <span style="color: #008000">//</span><span style="color: #008000">容器中有效元件個數 - 1</span>
  elementData[elementCount] = <span style="color: #0000ff">null</span>; <span style="color: #008000">//</span><span style="color: #008000">將向量的末尾位置設定為null</span>
  }</pre>

因為Vector底層是使用陣列實現的,所以它的操作都是對陣列進行操作,只不過其是可以隨著元素的增加而動態的改變容量大小,其實現方法是是使用Arrays.copyOf方法將舊資料拷貝到一個新的大容量陣列中。Vector的整個內部實現都比較簡單,這裡就不在重述了。

三、Vector遍歷

Vector支援4種遍歷方式。

3.1、隨機訪問

因為Vector實現了RandmoAccess介面,可以通過下標來進行隨機訪問。

for(int i = 0 ; i < vec.size() ; i++){
        value = vec.get(i);
    }

3.2、迭代器

Iterator it = vec.iterator();
    while(it.hasNext()){
        value = it.next();
        //do something
    }

3.2、for迴圈

for(Integer value:vec){
        //do something
    }

3.4、Enumeration迴圈

Vector vec = new Vector<>();
    Enumeration enu = vec.elements();
    while (enu.hasMoreElements()) {
        value = (Integer)enu.nextElement();
    }