Read_HashMap
来源:互联网 发布:mac 钥匙串访问 编辑:程序博客网 时间:2024/05/16 09:36
总结:
1. HashMap由数组和链表组成。
2. HashMap在put或查找时,首先取得key的hashcode,并与数组(length-1)做&位与操作,返回对应数组的下标位置
3. HashMap允许key为null,value为null;key为null,在table[0]下的链表中。
4. 初始容量(默认16)、加载因子(默认0.75)和最大容量(2的30次方)。
加载因子越大,对空间利用更充分,但查找的效率降低(链表长度变长);
加载因子越小,表中的数据过于稀疏(很多空间未使用,就扩容),对空间造成浪费5. resize()扩容操作是一个很耗时的操作。它需要重新计算这些元素在新的数组中的位置并通过迭代器复制处理。
6. containsKey()和containsValue()方法。前者直接通过key的hash值搜索对应的数组下标,然后通过链表查找。
后者要for循环嵌套遍历数组下的各个链表。
7. 核心代码
计算hashcode
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
根据hashcode定位数组索引
static int indexFor(int h, int length) {
return h & (length-1);
}
(以下来源:百度)
对哈希表的散列很自然地会想到用hash值对length取模(即除法散列法),Hashtable中也是这样实现的,这种方法基本能保证元素在哈希表中散列的比较均匀,但取模会用到除法运算,效率很低,HashMap中则通过h&(length-1)的方法来代替取模,同样实现了均匀的散列,但效率要高很多,这也是HashMap对Hashtable的一个改进。
哈希表的容量一定要是2的整数次幂。首先,length为2的整数次幂的话,h&(length-1)就相当于对length取模,这样便保证了散列的均匀,同时也提升了效率;其次,length为2的整数次幂的话,为偶数,这样length-1为奇数,奇数的最后一位是1,这样便保证了h&(length-1)的最后一位可能为0,也可能为1(这取决于h的值),即与后的结果可能为偶数,也可能为奇数,这样便可以保证散列的均匀性,而如果length为奇数的话,很明显length-1为偶数,它的最后一位是0,这样h&(length-1)的最后一位肯定为0,即只能为偶数,这样任何hash值都只会被散列到数组的偶数下标位置上,这便浪费了近一半的空间,因此,length取2的整数次幂,是为了使不同hash值发生碰撞的概率较小,这样就能使元素在哈希表中均匀地散列。
详细代码地址:https://github.com/Ahagpp/JAVA/blob/master/Collection/HashMap.java
0 0