java.util.HashMap
的OpenJDK代码包含以下行:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
为什么1 << 4
在这里使用,而不是16
?我很好奇。
答案 0 :(得分:21)
要强调的是,这个数字是2的幂,而不是完全随意的选择。因此,它提醒开发人员尝试使用不同的数字,他们应该使用模式中的其他数字(例如,1 << 3
或1 << 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
后的余数,再加上一步处理负散列值。这会起作用,但要慢一些。想象一下 decimal 中的一个例子,你有一些任意散列值193,498,212,任意表长度为1,234;这一点并不明显{ {1}}恰好是842,但是表长度是 10 的精确幂,193498212 % 1234
的结果只是212,最后3位。在二进制, 2 的幂是一个1后跟一些0,所以类似的技巧是可能的。)
答案 1 :(得分:10)
我无法理解开发人员的想法,但我们会做这样的事情来表明数字之间的关系。
比较一下:
int day = 86400;
VS
int day = 60 * 60 * 24; // 86400
第二个例子清楚地显示了数字之间的关系,而Java足够聪明,可以将其编译为常量。
答案 2 :(得分:0)
我认为原因是开发人员可以很容易地更改值(根据JavaDoc'/ *默认初始容量 - 必须是2的幂。* /')例如1 << 5
或{ {1}}并且他不需要做任何计算。