CodeGym /Java Blog /Toto sisi /Java 向量
John Squirrels
等級 41
San Francisco

Java 向量

在 Toto sisi 群組發布
您可能已經接觸過 Java 中的數組,並且知道它們的主要缺點之一是大小不變。一旦你創建了一個特定大小的數組,你就不能在以後改變它。Java語言中有幾個Java Collection框架類解決了這個問題。其中之一是 Java Vector Class。本文將對此進行討論。

什麼是向量類

正如我們在前言中所寫, Java Collection Framework 中的Vector類消除了數組的靜態大小問題。Java Vector 是一種動態數組,可以增大或縮小大小。使用Vector集合類,我們可以將一組元素存儲為簡單的對象,並通過各種方法對其進行操作。Vector 類可從java.util包中獲得。因此,如果您事先不知道數組的大小,或者如果您需要一個可以在程序的生命週期內改變維度的“數組”,則可以使用 Java 中的 Vector。必須馬上說Vectorclass 已經很老了,後來出現的 collections 可以在絕大多數情況下代替它。Java Vector 的流行“模擬”是ArrayList類。這些類之間最重要的區別是 Vector 是同步的,而 ArrayList 不是。我們將在稍後的“Vector 類有什麼問題”部分 討論這兩個類之間的其他差異以及 Vector 類的更現代的類似物。

Java 向量方法

以下是 Java向量方法:
  • void add(int index, Object element)在向量的指定位置插入指定元素。

  • boolean add(Object o)將指定元素添加到向量的末尾。

  • boolean addAll(Collection c)將指定集合中的所有元素添加到向量的末尾,按照它們由指定集合迭代器返回的順序。

  • boolean addAll(int index, Collection c)將指定 Collection 中的所有元素插入向量中的指定位置。

  • void addElement(Object obj)將指定組件添加到此向量的末尾,將其大小增加一。

  • int capacity()返回此向量的當前容量。

  • void clear()從此向量中刪除所有元素。

  • 對象 clone()返回此向量的克隆。

  • boolean contains(Object elem)測試指定對像是否是此向量中的一個組件。

  • boolean containsAll(Collection c)如果向量包含指定 Collection 的所有元素,則返回 true。

  • void copyInto(Object[] anArray)將此向量的組件複製到指定數組。

  • Object elementAt(int index)返回指定索引處的組件。

  • Enumeration elements()返回此向量的組件的枚舉。

  • 如有必要,void ensureCapacity(int minCapacity)會增加此向量的容量,以確保它至少可以容納最小容量參數給定的組件數。

  • boolean equals(Object o)將指定對象與此向量進行比較。

  • Object firstElement()返回此向量的第一個組件(索引為 0 的元素)。

  • Object get(int index)返回此向量中指定位置的元素。

  • int hashCode()返回此向量的散列碼值。

  • int indexOf(Object elem)搜索給定參數的第一次出現,使用 equals 方法測試是否相等。

  • int indexOf(Object elem, int index)從 index 開始搜索給定參數的第一次出現,並使用 equals 方法測試是否相等。

  • void insertElementAt(Object obj, int index)將指定對像作為一個組件插入此向量中的指定索引處。

  • boolean isEmpty()測試此向量是否缺少組件。

  • Object lastElement()返迴向量的最後一個分量。

  • int lastIndexOf(Object elem)返回指定對像在該向量中最後一次出現的索引。

  • int lastIndexOf(Object elem, int index)從指定索引開始向後搜索指定對象,並將索引返回給它。

  • Object remove(int index)移除此向量中指定位置的元素。

  • boolean remove(Object o)移除此向量中第一次出現的指定元素。如果向量不包含元素,則它不會改變。

  • boolean removeAll(Collection c)從包含在指定 Collection 中的向量中移除所有元素。

  • void removeAllElements()從向量中刪除所有組件並將其大小設置為零。

  • boolean removeElement(Object obj)從此向量中移除第一個(最低索引)出現的參數。

  • void removeElementAt(int index)刪除索引處的元素。

  • protected void removeRange(int fromIndex, int toIndex)從這個 List 中移除所有索引在 fromIndex 和 toIndex 之間的元素。

  • boolean retainAll(Collection c)僅保留向量中包含在指定 Collection 中的元素。

  • Object set(int index, Object element)將此向量中指定位置的元素替換為指定元素。

  • void setElementAt(Object obj, int index)將此向量的指定索引處的組件設置為給定對象。

  • void setSize(int newSize)設置此向量的大小。

  • int size()返回此向量中的分量數。

  • List subList(int fromIndex, int toIndex)返回此列表在 fromIndex(包含)和 toIndex(獨占)之間的部分的表示(視圖)。

  • Object[] toArray()返回一個數組,該數組以正確的順序包含此向量的所有元素。

  • Object[] toArray(Object[] a)以正確的順序返回包含此向量的所有元素的數組;返回數組的執行類型是指定數組的類型。

  • String toString()返回此向量的字符串表示形式,其中包含每個元素的字符串表示形式。

  • void trimToSize()將此向量的容量修剪為向量的當前大小。

Java 向量示例


import java.util.Vector;

public class VectorExample {

   public static void main(String[] args) {
       Vector vector = new Vector();
       System.out.println("the size of the empty vector = " +  vector.size());
       //adding some vector elements
       vector.add("Johnny");
       vector.add("Ivy");
       vector.add("Ricky");
       System.out.println(vector); 
       
       //adding more vector elements       
       vector.add("Johnny");
       vector.add("Paul");
       System.out.println(vector);
       System.out.println("the size of the vector = " +  vector.size());
       System.out.println("the first element of the vector = " + vector.firstElement());

       //here the program will print out the first appearance of "Johnny" element
       System.out.println(vector.indexOf("Johnny"));
       //program will print out the first appearance of "Johnny" element starting from the element 1
       System.out.println(vector.indexOf("Johnny", 1));
       vector.clear(); //deleting all vector elements
       System.out.println("the size of the vector after clear method = " +  vector.size());

   }
}
該程序的輸出如下:
空向量的大小 = 0 [Johnny, Ivy, Ricky] [Johnny, Ivy, Ricky, Johnny, Paul] 向量的大小 = 5 向量的第一個元素 = Johnny 0 3 清除後向量的大小方法 = 0

Vector 類有什麼問題?

根據Java Vector類的文檔,如果你的程序中不需要線程安全的實現,建議使用ArrayList代替Vector(Collection Framework更有效的參與者)。讓我們稍微改變一下上面的示例,使用ArrayList類而不是Vector

import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {

       public static void main(String[] args) {
           List vector = new ArrayList();
           //Vector vector = new Vector();
           System.out.println("the size of the empty vector = " +  vector.size());
           vector.add("Johnny");
           vector.add("Ivy");
           vector.add("Ricky");
           System.out.println(vector);
           vector.add("Johnny");
           vector.add("Paul");
           System.out.println(vector);
           System.out.println("the size of the vector = " +  vector.size());
           //System.out.println("the first element of the vector = " + vector.firstElement());

           //here the program will print out the first appearance of "Johnny" element
           System.out.println(vector.indexOf("Johnny"));
           //program will print out the first appearance of "Johnny" element starting from the element 1
           //System.out.println(vector.indexOf("Johnny", 1));
           vector.clear();
           System.out.println("the size of the vector after clear method = " +  vector.size());

       }
   }
我們用vector.indexOf("Johnny", 1) 註釋掉了這一行,因為在ArrayList類的這個變體中沒有這樣的方法。出於同樣的原因,vector.firstElement()行被註釋掉了。在所有其他方面,該程序產生與第一個相同的結果。當然,在這樣的例子中,並不清楚為什麼ArrayListVector更好。這需要更多關於線程的知識。我們在這裡列出原因。首先,雖然Vector類是synchronized的,但不能稱之為完全線程安全的,雖然這看起來很奇怪。事實是Vector同步每個操作,而不是整個Vector實例本身。在需要同步整個操作集而不是單個操作的程序中,這可能是一個問題。比如說,如果一個線程正在迭代一個向量而另一個線程正在結構上修改向量的一個實例,則迭代器將拋出一個ConcurrentModificationException。事實證明,如果兩個線程執行不同的操作,則它們可以同時處理一個Vector實例。其次,矢量類沒有最好的性能,因為它的對像有一個可調整大小的數組和同步。這種組合意味著阻塞操作的額外開銷,無論是否需要同步。當然,這會影響性能。此外,在每個操作上同步向量也會對性能產生負面影響,因為我們會為每個操作一次又一次地獲取鎖。如果類的整個實例都被同步,那麼鎖也被獲取一次,效率會高很多。第三,Vector支持一些遺留方法。例如元素(). 此方法返迴向量組件的枚舉。出於多種原因,程序員最常使用 Iterator 或 ListIterator 來枚舉。特別是,Enumeration 沒有定義remove()方法,這意味著列表不能在迭代期間進行結構修改。此外,與 ListIterator 不同,Enumeration 不提供雙向訪問。如您所見,Vector有不少問題。如果您仍然需要 List 接口的線程安全實現怎麼辦?在這種情況下,ArrayList將無濟於事,但您可以使用CopyOnWriteArrayList類而不是Vector它被定位為ArrayList的線程安全變體. 您還可以使用 Collections synchronizedList()方法來同步ArrayList

Vector 確實有一些問題……為什麼它仍然在 Java 中,為什麼要教它?

問題來了:我們到底為什麼要研究Vector類?為什麼它還沒有從 Java 中刪除?事實上,Java 奉行向後兼容的原則。這意味著所有多年前編寫的舊代碼都將被現代版本的 Java 理解。此外,Java環境中有相當多的企業級應用已經支持了幾十年。您很有可能在工作中不得不與這樣的“恐龍”打交道,因此您需要做好應對意外的準備,例如帶有無效遺留類的代碼。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION