什么是矢量容量的目的

时间:2010-05-07 09:07:46

标签: java

Vector API定义了4种不同的构造函数:

Vector()

Vector(Collection<? extends E> c)

Vector(int initialCapacity)

Vector(int initialCapacity, int capacityIncrement)

但它们如何运作以及它们用于什么?我为什么要为矢量定义固定容量?即使我将初始容量设置为100,我也可以向向量添加101.项:

Vector<Object> test = new Vector<Object>(100);
for (int i = 0; i < 100; i++) {
    test.add(new Object());
}

test.add(new Object());
System.out.println(test.size());
System.out.println(test.capacity());

在上面的代码中,第二个sysout(test.capacity())写入200.为什么此向量中的容量为200?初始容量为100,我没有定义容量增量。

我真的很想知道是否有使用这些建筑师的现实世界的例子?

一个熟悉的问题: 究竟是Vector.get(int position)和Vector.elementAt(int position)之间的区别?我读到在将Vector添加到Collection类之前定义了get方法,因此有必要在以后添加方法elementAt(int position)。真的吗?或者还有其他差异吗?

2 个答案:

答案 0 :(得分:21)

什么是“初始”容量?

初始容量就是:Vector在施工时的容量。

Vector是一个可动态增长的数据结构,它会根据需要重新分配其后备阵列。因此,没有最终容量,但您可以设置其初始值。

以下摘自Vector API

  

每个向量都会尝试通过维护capacitycapacityIncrement来优化存储管理。 capacity始终至少与向量size一样大;它通常更大,因为随着组件被添加到向量中,向量的存储以capacityIncrement的大小增加。应用程序可以在插入大量组件之前增加向量的capacity;这减少了增量重新分配的数量。

注意构建后,您也可以使用ensureCapacity来达到同样的效果。

另见


为什么重要?

例如,假设您有100个要插入Vector的元素。 nullary constructorVector设置为初始容量为10,并且在增长时大小翻倍。这意味着要容纳100个元素,它可以加倍到20,40,80,最后是160,然后才能适应所有100个元素。

请注意,执行了4个增量重新分配步骤,当它最终适合所有100个元素时,仅使用60%的实际容量。另一方面,在插入之前ensureCapacity(100)(或使用适当的构造函数重载来实现相同的效果)将使该过程更有效,因为没有多余的未使用容量,并且该阵列只需要重新分配一次。

请注意渐近,上面的两个过程同样是最优的O(N)时间和O(N)空间),但当然后者是一个恒定时间的改进在空间和时间都超过前者。

当然,如果你设置ensureCapacity(10000000),并且只插入100个元素,那么你只能使用.001%的容量 - 真是浪费!因此,如果您提前知道要插入多少元素,则可以使用ensureCapacity使该过程更有效(通过常数因子),但无论如何Vector仍然可以即使没有你的帮助,它本身也很好。

另见


为什么加倍?

没有详细说明,这种增长倍增是几何扩展的一种形式,这使Vector的每次操作能够进行恒定时间摊销分析。值得注意的是ArrayList,一个由数组支持的类似可扩展数据结构,甚至没有指定其增长策略的细节,但OpenJDK version的增长因子为3/2

请注意,Vector实际上允许您使用capacityIncrement设置非几何增长因子。 重要的是要认识到,如果将 capacityIncrement 设置为非零的小值,实际上可以使 Vector 执行可怕的操作渐近即可。例如,如果您将其设置为1,则添加N元素将是O(N^2)操作!

ArrayList不允许您自定义其增长政策,因为您甚至不应该知道(也不关心,真的!)。

另见


  

elementAtget呢?

直接来自the documentation

  

从Java 2平台v1.2开始,这个类被改进以实现List接口,使其成为Java Collections Framework的成员。与新的集合实现不同,Vectorsynchronized

     

public E elementAt(int index):返回指定索引处的组件。此方法的功能与get(int)方法(属于List接口的一部分)相同。

按时间顺序排列,VectorelementAt实施List之前已经get,因此必须实施Vector

请注意synchronizedArrayList的部分。如果您不需要此功能,{{1}}将是一个更好的选择,因为您没有支付线程安全的费用。

另见

答案 1 :(得分:3)

如果指定零容量或负容量增量,则每次加载矢量的容量,根据capacityIncrement字段的文档:

  

容量的数量   矢量是自动的   当它的大小变小时递增   超过其容量。如果   容量增量小于或   等于零,容量   每次需要时,矢量加倍   成长。

如果您只指定容量,则默认capacityIncrement为零 - 因此加倍行为。

如果你已经很清楚你的收藏需要多大,你就可以指定容量 - 这可以避免不必要的复制。

至于getelementAt() - 是的,为常规集合API添加了elementAt()。查看实现,除了错误情况中抛出的异常的精确细节之外,它们是相同的。