static final int MAXIMUM_CAPACITY = 1 << 30;
/**
- Returns a power of two size for the given target capacity.
- 返回 大于等于cap 且 最接近cap 的2的幂次方的值
*/
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
我们分步骤解析一下这个函数:
>>>
无符号右移运算符,高位用0 填充。如下:
a = 1010
a >>> 1 = 0101
|
如果相对应位都是 0,则结果为 0,否则为 1。如下:
a = 1010
b = 0011
a | b = 1011
|=
,a |= b
等同于a = a|b
。
这时候我们就能看懂 n |= n >>> 1
; 等同于 n = n | n >>> 1
-
int n = cap - 1;
是因为如果cap不减1,当 cap 本来就是2次幂数值,就会导致返回的结果为 cap*2 。 -
我们带入一个值看下运行结果,假设 cap = 20
static final int tableSizeFor(int cap) {
System.out.println("cap = "+ Integer.toBinaryString(cap));
int n = cap - 1;
System.out.println("n = "+ Integer.toBinaryString(n));
n |= n >>> 1;
System.out.println("n1 = "+ Integer.toBinaryString(n));
n |= n >>> 2;
System.out.println("n2 = "+ Integer.toBinaryString(n));
n |= n >>> 4;
System.out.println("n4 = "+ Integer.toBinaryString(n));
n |= n >>> 8;
System.out.println("n8 = "+ Integer.toBinaryString(n));
n |= n >>> 16;
System.out.println("n16 = "+ Integer.toBinaryString(n));
System.out.println("n+1 = "+ Integer.toBinaryString(n+1));
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
@Test
public void tableSizeForTest(){
System.out.println(“tableSizeFor:”+ tableSizeFor(20));
}
我这里直接把tableSizeFor(int cap) 拷贝出来,然后添加了日志。结果如下:
cap = 10100
n = 10011
n1 = 11011 (10011 | 01001)
n2 = 11111 (11011 | 01101)
n4 = 11111 (11111 | 01111)
n8 = 11111 (11111 | 01111)
n16 = 11111 (11111 | 01111)
n+1 = 100000 (11111 + 1)
tableSizeFor:32
HashMap(Map<? extends K, ? extends V> m) 构造函数
我们来看下最后一个构造函数,参数是一个Map ,loadFactor 设置为默认的 0.75,然后putMapEntries(m, false) 函数,把参数Map 的值拷贝到构造的HashMap 中去。
接着我们看下putMapEntries(m, false) 这个函数的具体实现
putMapEntries(m, false) 函数
/**
- 在 putAll 和 构造函数 中被调用
- @param m the map
- @param 构造函数调用是传 false,否则传true
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // 构造函数调用是 table = null
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t);
}
else if (s > threshold)
resize();
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict);
}
}
}
可以看到,当构造函数调用putMapEntries(Map<? extends K, ? extends V> m, boolean evict) 函数时,通过参数map 的size 设置threshold ,然后调用putVal() 函数设置内容。putVal() 我们在后面讲 put 的时候再具体分析。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。
因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频**
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-CQoh5wrX-1712520254142)]