HashMap之get()剖析

上次我们已经剖析了put()方法,这次来看看get()方法。

1.HashMap的get()方法剖析:

public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

可见,也是将key值进行hash()之后,找到对应的桶数组,再调用getNode()进行查找。

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) {
            //若在一个桶中,并且当前索引位置的key值与要查找的key值相等
            //说明找到了,返回该值
            if (first.hash == hash && 
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
                //若key值不相同,且还有元素
            if ((e = first.next) != null) {
                //如果此时已经树化,则调用红黑树的getTreeNode()查找
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {
                    //若没有树化,则在从前往后遍历链表,直到找到该元素
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        //若找不到则返回null
        return null;
    }

2.get()方法流程总结:

  • 首先判断桶数组是否为空,若为空直接返回null。
  • 若桶数组不为空,则计算索引,查看当前索引是否有元素,若有元素,查看key值是否相同。若key值相同,则返回该节点。
  • 若key值不相同,则继续查找,先判断是否树化,若已经树化,则调用红黑树的getTreeNode()进行查找。
  • 若没有树化,则从前往后遍历链表,找到了则返回节点,找不到则返回null。

3.HashMap源码剖析总结:

  • 为什么我们不用hashCode()方法计算的出来的hash值作为桶下标呢?
    因为hashCode()计算出来的hash值太大,需要大量的存储空间;而且这样哈希表就跟普通的数组差不多。

  • 为什么我们要保证哈希表的长度为2^n?
    一方面是为了保证哈希表中所有的元素都被访问到,一定程度上避免哈希碰撞;
    一方面是为了提高运算速度。
    当我们计算元素在哈希表中的索引下标时,采用 i = hash&(n-1),假如我们此时的n为8,则(n-1)=7=0111,就保证了在0-7的范围内,不会发生哈希碰撞,因为此时的i的相与结果完全取决于我们计算出来的hash值。

  • 为什么在hash()中计算桶下标要进行(h>>>16)?
    这样保留了高16位,使得高低16位都参与异或运算,降低了哈希冲突的概率。

4.树化的条件:

  • 当前桶中的链表长度>=8,并且哈希表的长度>=64时,会树化,否则只是进行简单的扩容。
  • 加入红黑树是为了提高由于链表过长而造成的查询效率降低,将时间复杂度由O(n)提升为O(logn)。

5.扩容的条件:当桶数组的容量>12时进行扩容。

6.解树化的条件:当红黑树的节点个数<=6时,会将红黑树转为链表。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,使用HashMap的get方法可以根据给定的键获取对应的值。在给定的代码中,可以使用以下方式来获取值: ```java String value = map.get(key); ``` 其中,`map`是一个HashMap对象,`key`是要获取值的键。这个方法会返回与给定键关联的值,如果键不存在,则返回null。\[1\]在HashMap的实现中,get方法会根据键的哈希值来确定存储位置,并通过比较键的相等性来找到对应的值。\[2\]\[3\] #### 引用[.reference_title] - *1* [Java 中HashMap 详解](https://blog.csdn.net/java1527/article/details/126850576)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Java-HashMap(hash函数、put函数、get函数源码分析)](https://blog.csdn.net/wahehe__/article/details/113704273)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [HashMap之get方法详解](https://blog.csdn.net/weixin_39667787/article/details/86687414)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值