为什么要将 HashSet<>(0) 初始化为零?

21

我喜欢使用 HashSet<>(),并且在使用默认构造函数进行初始化时会迫不及待地使用它:

Set<Users> users = new HashSet<>();

现在,我的自动Bean创建器(JBoss工具)将其初始化为:

Set<Users> users = new HashSet<>(0);

为什么是 ?API告诉我这是初始容量,但将其设为零有什么优势?这种做法可行吗?

5个回答

21

默认初始容量为16,因此如果您最终不向集合中添加任何内容,则通过传入0可以节省一些内存空间。

除此之外,没有实际优势;当您传入0时,集合将被创建为容量为1,并且一旦添加了东西,它就必须被重新调整大小。


@PeterLawrey,怎么回事?不是2吗? - Damian Leszczyński - Vash
@PeterLawrey,这是2。必须是大于等于2的二的幂。请查看HashMap(int,int)的构造函数。 - Damian Leszczyński - Vash
4
@Vash 1 是2的幂。从HashMap中:// 找到一个大于等于initialCapacity的2的幂 int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; - Peter Lawrey
@PeterLawrey,是的,我们没有将移位设为1<0,因此我们仍然保持为1。 - Damian Leszczyński - Vash

6

HashSet使用HashMap来存储数据:

public HashSet(int initialCapacity) {
map = new HashMap<E,Object>(initialCapacity);
}

当 initialCapacity = 0 时,

public HashMap(int initialCapacity, float loadFactor) {
    ....
    // Find a power of 2 >= initialCapacity
    int capacity = 1;
    while (capacity < initialCapacity)
        capacity <<= 1;
}

HashMap的容量为1

但如果使用默认构造函数:

public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
    table = new Entry[DEFAULT_INITIAL_CAPACITY];
    init();
}

HashMap的容量为16*0.75

因此,在初始化时使用new HashSet<>(0)可以节省一些内存。


5

这将把它设置为最小值。

很可能用于关闭代码分析器,如果您没有为集合设置初始容量,则可能会发生错误。通过将其设置为0,您只是将其设置为最小值。

这不是很优化,因为一旦添加一个条目,负载因子为0.7将使容量为2,在此过程中重新创建Map.Entry[]


3

如果你看到了文档

这里有一些线索。

在此集合上进行迭代所需的时间与 HashSet 实例的大小(元素数量)和支持 HashMap 实例(桶的数量)的“容量”之和成比例。因此,如果迭代性能很重要,不要将初始容量设置得太高(或负载因子过低)。


0

HashMap的初始负载因子为16。当HashMap保存12条记录的数据时,这相当于其初始大小的75%。此时HashMap会增加其大小。

因此,在构造函数中将初始容量设置为0即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接