CodeGym /Java 博客 /随机的 /Java 向量
John Squirrels
第 41 级
San Francisco

Java 向量

已在 随机的 群组中发布
您可能已经接触过 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