什么是矢量容量的目的
Vector API定义了4种不同的构造函数:
Vector() Vector(Collection c) Vector(int initialCapacity) Vector(int initialCapacity, int capacityIncrement)
但它们如何运作以及它们用于什么? 我为什么要为矢量定义固定容量? 即使我将初始容量设置为100,我也可以向向量添加101.项:
Vector test = new Vector(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)。 真的吗? 或者还有其他差异吗?
什么是“初始”容量?
初始容量就是: Vector
在施工时的容量。
Vector
是一种动态可扩展的数据结构,它会根据需要重新分配其后备arrays。 因此,没有最终容量,但您可以设置其初始值。
这是Vector
API的摘录:
每个向量都试图通过维持
capacity
和capacityIncrement
来优化存储管理。capacity
始终至少与矢量size
一样大; 它通常更大,因为随着组件被添加到向量中,向量的存储以块的大小增加capacityIncrement
的大小。 应用程序可以在插入大量组件之前增加向量的capacity
; 这减少了增量重新分配的数量。
注意构建后,也可以使用ensureCapacity
来达到同样的效果。
也可以看看
- 创建集合对象(List,Set等)时,通常会使用称为“initialCapacity”的参数。 这个参数意味着什么,它是如何使用的?
为什么这有关系?
例如,假设您有100个要插入Vector
元素。 Nullary构造函数将Vector
设置为初始容量为10,并且在生长时将其大小增加一倍。 这意味着要容纳100个元素,在它可以容纳所有100个元素之前,它将加倍到20,40,80,然后最终加倍160。
请注意,执行了4个增量重新分配步骤,当它最终适合所有100个元素时,仅使用60%的实际容量。 另一方面,在插入之前使用ensureCapacity(100)
(或使用适当的构造函数重载来实现相同的效果)将使该过程更有效,因为没有多余的未使用容量,并且该arrays只需要重新分配一次。
请注意, 渐近地,上述两个过程同样是最优的 ( O(N)
时间和O(N)
空间),但当然后者在空间和时间上都是对前者的恒定时间改进。
当然,如果你设置了ensureCapacity(10000000)
,并且只插入了100个元素,你只能使用.001%的容量 – 真是浪费! 因此,如果您提前知道要插入多少元素,则可以通过使用ensureCapacity
使过程更有效(通过常数因子),但无论如何,即使没有您的Vector
仍可以自己完成一项很好的工作。救命。
也可以看看
- Java Set初始容量最佳实践
为什么加倍?
没有详细说明,这种增长倍增是几何扩展的一种forms,这使得Vector
每次操作能够进行恒定时间摊销分析。 值得注意的是,由数组支持的类似可扩展数据结构ArrayList
甚至没有指定其增长策略的细节,但OpenJDK版本的增长因子为3/2
。
请注意, Vector
实际上允许您使用capacityIncrement
设置非几何增长因子。 重要的是要意识到如果你将 capacityIncrement
设置 为一个小的非零值,你实际上可以使 Vector
执行可怕的渐进式 。 例如,如果将其设置为1
,则添加N
元素将是O(N^2)
操作!
ArrayList
不允许您自定义其增长策略,因为您甚至不应该知道(也不关心,真的!)。
也可以看看
- 维基百科:动态数组
- 请参阅: 几何扩展和摊销成本
杂
那么
elementAt
又get
什么?
直接来自文档 :
从Java 2平台v1.2开始,这个类被改进以实现
List
接口,使其成为Java Collections Framework的成员。 与新的集合实现不同,Vector
是synchronized
。
public E elementAt(int index)
:返回指定索引处的组件。 此方法的function与get(int)
方法(它是List
接口的一部分)相同。
所以按时间顺序, Vector
有了elementAt
,在它被改装以实现List
,因此必须实现get
。
请注意有关Vector
正在synchronized
的部分。 如果您不需要此function, ArrayList
将是一个更好的选择,因为您不需要支付线程安全的成本。
也可以看看
- 如果线程安全性不是问题,则使用Java中的ArrayList与Vectors
如果指定零容量或负容量增量,则每次都会将向量的容量加倍,具体取决于capacityIncrement
字段的文档:
当矢量大小超过其容量时,矢量容量自动递增的量。 如果容量增量小于或等于零,则每次需要增长时,矢量的容量加倍。
如果仅指定容量,则默认的capacityIncrement
为零 – 因此是倍增行为。
如果您已经很好地了解了集合需要多大的数量,那么您可以指定容量 – 这可以避免不必要的复制。
至于get
和elementAt()
– 是的,为通用集合API添加了elementAt()
。 查看实现,除了错误情况中抛出的exception的精确细节之外,它们是相同的。