算法与数据结构 (八) HashMap源码
2020-12-13 03:16
标签:解决 元素 改变 tin 长度 ppi 函数 ble als put(key,value)内部调用的是putVal() 下面是源码 jdk1.8采用的是尾插法 代码除了红黑树的部分引出两个部分:1. 为什么采取hash & 长度-1 的方式找数组位置 2. 如何扩容 定容量的方法: 对于构造函数中传入的整数,进行如下操作。结论就是得到的数,是大于等于传入值的最小 2 的幂。也就是传入64 就是64 ,传入127 就是 128。 这算法想起来不好想,但看代码还是好理解。对于65这种,减去1,就是 100 0000 第一次运算 是110 0000 第二次: 111 1000,结果变成1111111(全1) 最后加上1 必然是2 的整次幂。 这也解决了 hash运算为什么用 hash & n-1,因为&的效率大于除法和取余运算,而且由于是2的整次幂,按位与和取余操作效果一样,但是速度更快。 此外 node节点中的hash 值 ,是这样得到的,也就是原来key hashcode高16位和hashcode亦或。为的是增加高16位的参与感,减少hash冲突,如果key的hashcode 是 0A01 0B01 0C01 如果直接进行 按位与操作,那么他们都被映射到同一个位置,而经过这么一轮操作会,会减少hash碰撞的情况。 1 .hash值的算法,键的hash值与 高16亦或,保留高位信息 ---映射下标值 &(容量-1)得到实际的 2. 保证容量是2的幂 采取按位或 3. .hashMap的结构 在1.8做出的改变,数组加红黑树 链表大于8就会变树, 变树的代价比较高,所以还增加了一个条件,就是数组大小要大于64,否则采取扩容的方法,解决链表过长的问题。 4.hashmap可以插入空值键 有单独的方法,永远插在第一个链表,也就是数组下标为0的位置 5.遍历方法 map.entrySet() 这是拿到了所有的键值对 keyset() 这个是拿到了所有的键值 6.并发下的问题 put()丢失更新 resize()也可能丢失更新 算法与数据结构 (八) HashMap源码 标签:解决 元素 改变 tin 长度 ppi 函数 ble als 原文地址:https://www.cnblogs.com/caijiwdq/p/11072465.html一 存储结构
static class Node
final int hash;
final K key;
V value;
Node
}transient Node
内部存储的单元如上所示,整体上就是数组加链表的桶状结构。二 put操作
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node
//以下代码好像是为了linkedhashmap服务的
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
// 如果容量超了 就扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
三 初始化和扩容
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 = MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
而扩容主要是resize方法 主要是这段代码 ,新的数组是旧的数组的二倍,如下是旧的数据迁移到新数组中if (oldTab != null) {
for (int j = 0; j e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null) //第一种情况,节点就一个元素
newTab[e.hash & (newCap - 1)] = e; //当前节点在新节点中的位置
else if (e instanceof TreeNode) //第二种情况,节点是红黑树
((TreeNode
四 总结
上一篇:python中的格式化