详解HashMap集合( 八 )


2)我们可以看到在putVal()方法中key在这里执行了一下hash()方法,来看一下Hash方法是如何实现的 。
static final int hash(Object key){int h;/*1)如果key等于null:可以看到当key等于null的时候也是有哈希值的 , 返回的是0.2)如果key不等于null:首先计算出key的hashCode赋值给h,然后与h无符号右移16位后的二进制进行按位异或得到最后的hash值*/return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }从上面可以得知HashMap是支持Key为空的 , 而HashTable是直接用Key来获取HashCode所以key为空会抛异常 。
{其实上面就已经解释了为什么HashMap的长度为什么要是2的幂因为HashMap 使用的方法很巧妙 , 它通过 hash/*1)如果key等于null:可以看到当key等于null的时候也是有哈希值的 , 返回的是0.2)如果key不等于null:首先计算出key的hashCode赋值给h,然后与h无符号右移16位后的二进制进行按位异或得到最后的hash值*/return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }在putVal函数中使用到了上述hash函数计算的哈希值:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {。。。。。。。。。。。。。。if ((p = tab[i = (n - 1) }final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node[] tab; Node p; int n, i;/*1)transient Node[] table; 表示存储Map集合中元素的数组 。2)(tab = table) == null 表示将空的table赋值给tab,然后判断tab是否等于null , 第一次肯定是null3)(n = tab.length) == 0 表示将数组的长度0赋值给n,然后判断n是否等于0 , n等于0由于if判断使用双或 , 满足一个即可 , 则执行代码 n = (tab = resize()).length; 进行数组初始化 。并将初始化好的数组长度赋值给n.4)执行完n = (tab = resize()).length , 数组tab每个空间都是null*/if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;/*1)i = (n - 1) 根据键值对创建新的节点放入该位置的桶中小结:如果当前桶没有哈希碰撞冲突 , 则直接把键值对插入空间位置*/if ((p = tab[i = (n - 1)else {// 执行else说明tab[i]不等于null , 表示这个位置已经有值了 。Node e; K k;/*比较桶中第一个元素(数组中的结点)的hash值和key是否相等1)p.hash == hash :p.hash表示原来存在数据的hash值hash表示后添加数据的hash值 比较两个hash值是否相等说明:p表示tab[i] , 即 newNode(hash, key, value, null)方法返回的Node对象 。Node newNode(int hash, K key, V value, Node next){return new Node<>(hash, key, value, next);}而在Node类中具有成员变量hash用来记录着之前数据的hash值的2)(k = p.key) == key :p.key获取原来数据的key赋值给kkey 表示后添加数据的key 比较两个key的地址值是否相等3)key != null// hash值不相等或者key不相等;判断p是否为红黑树结点else if (p instanceof TreeNode)// 放入树中e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);// 说明是链表节点else {/*1)如果是链表的话需要遍历到最后节点然后插入2)采用循环遍历的方式 , 判断链表中是否有重复的key*/for (int binCount = 0; ; ++binCount) {/*1)e = p.next 获取p的下一个元素赋值给e2)(e = p.next) == null 判断p.next是否等于null , 等于null , 说明p没有下一个元素 , 那么此时到达了链表的尾部 , 还没有找到重复的key,则说明HashMap没有包含该键将该键值对插入链表中*/if ((e = p.next) == null) {/*1)创建一个新的节点插入到尾部p.next = newNode(hash, key, value, null);Node newNode(int hash, K key, V value, Node


推荐阅读