为什么用1 << 4而不是16?

问题描述 投票:10回答:3

java.util.HashMap的OpenJDK代码包括以下行:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

为什么1 << 4在这里使用,而不是16?我很好奇。

java openjdk
3个回答
21
投票

需要强调的是,这个数字是2的幂,而不是完全随意的选择。因此,它提醒开发人员尝试不同的数字,他们应该使用模式中的其他数字(例如,1 << 31 << 5,而不是20),因此他们不会破坏依赖于两个要求的力量的方法。有一个评论just above

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

任何java.util.HashMap的容量(表长度)总是2的幂。它的设计方式是因为它允许使用快速按位AND运算(&)将每个键的哈希码包装到表的长度范围内,如in methods that access the table所做:

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) { /// <-- bitwise 'AND' here
        ...

在那里,n是容量,(n - 1) & hash包装哈希值以适应该范围,为该哈希选择适当的表桶。

(如果n不是2的幂,那么公式需要是Math.abs(hash % n),使用模运算符来计算n除法后的余数,加上一个额外的步骤来处理负哈希值。这会起作用,但要慢一些。想象一个十进制的例子,你有一些任意哈希值193,498,212,任意表长度为1,234; 193498212 % 1234恰好是842并不明显,但是表长度是10的精确幂,193498212 % 1000的结果简单地说就是212,最后3位数。在二进制中,2的幂是1然后是0的一些数,所以类似的技巧是可能的。)


10
投票

我无法读懂开发人员的想法,但我们会这样做以表明数字之间的关系。

比较一下:

int day = 86400;

VS

int day = 60 * 60 * 24; // 86400

第二个例子清楚地显示了数字之间的关系,而Java足够聪明,可以将其编译为常量。


0
投票

我认为原因是开发人员可以很容易地更改值(根据JavaDoc'/ *默认初始容量 - 必须是2的幂。* /')例如1 << 51 << 3他不需要做任何计算。

© www.soinside.com 2019 - 2024. All rights reserved.