zoukankan      html  css  js  c++  java
  • hashmap源码探究

    hashmap简介

    public class HashMap<K,V> extends AbstractMap<K,V>
        implements Map<K,V>, Cloneable, Serializable {
    

    hashmap概念

    HashMap又叫哈希表、散列表,是一种以键值对方式存储数据的数据结构,它利用不重复无序的键实现了快速查找。

    hashmap实现图

    数组+链表+红黑树(jdk8) 每个数组存的是一个entry

    为什么hashmap能允许k,v为null,而hashtable不允许

    hashmap

    hashmap的hash方法源码

    解释:hashmap里有个hash方法,进行判断,如果key为null会令hash值为0,否则高16与低16异或,,,其他方法会调用hash方法进行操作,而hashtable会调用hashcode方法进行操作,当key为null时,还调用hashcode方法的话会产生空指针异常(下面有详细介绍)

    演示:

    hashtable

    首先hashtable的源码中没有像hashmap中的hash方法

    然后看hashtable的put方法

    解析:

    • 第一个框:清楚的表示 如果加入一个value为null则丢出空指针异常
    • 第二个框:可以思考出,如果key为null,还调用hashcode方法,肯定也抛出空指针异常

    演示

    hashmap的get方法详解

    首先get方法的作用为用key取value

    get方法源码

    从get方法看出先去调用了getnode方法返回值赋给e,可以大致猜测getnode的作用是通过key取到entry对象

    getnode方法源码

    解析:

    第一个if:

    if ((tab = table) != null && (n = tab.length) > 0 &&
                (first = tab[(n - 1) & hash]) != null) {
    

    table变量:

    resize()方法初始化:就是一个数组 也就是开头的那个数组

    再看第一个if :判断数组是否为null,数组长度是否大于0,还有一个与运算求出在数组中的也是其链表第一个的entry是否为null,有一个不成立则return null;

    简单测试:

    第二个if

    if (first.hash == hash && // always check first node
                    ((k = first.key) == key || (key != null && key.equals(k))))
                    return first;
    

    其中first

    first = tab[(n - 1) & hash]
    

    表的长度减1和key的hash取与 找出entry所在链表的第一个entry

    判断hash值,key值key的equals是否相等 若相等返回第一个

    第三个if

    if ((e = first.next) != null) {
                    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);
                }
    

    第三个if是用了do while循环遍历hash值相等的该链表

    key.equals(k):用了equels,这也是为什么对象作为key需要重写hashcode和equals的原因

    找到就返回该entry

    看完这个方法,再看get方法就容易理解了

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

    总结:通过getNode去找,找不到就返回null,找到了就返回其valuse值

    hashmap的put方法详解

    put源码

     public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);
        }
    

    参数解释

     /**
         * Implements Map.put and related methods.
         *
         * @param hash hash for key
         * @param key the key
         * @param value the value to put
         * @param onlyIfAbsent if true, don't change existing value
         		只有为真时,才不要更改现有值   
         * @param evict if false, the table is in creation mode.
         	如果为false,则该表处于创建模式。
         * @return previous value, or null if none
         */
    
    首先判断table,也就是数组是否为空,为空的话就去使用inflateTable的方法(这里不多解释)初始化hashmap。
    
       如果table不为空的话,就判断key是否为空,为空的话就将放到数组的index=0的位置,如果value不为空则返回value值。
    
       如果key不为空的话,就通过key获取hash值,通过hash值和table的长度与运算获取hashCode值。
    
       通过hashCode的遍历entry<K,V>的键值对,如果key的hash值相等 并且key.equals(e.key)也相等的话,就将新的value替换掉旧的,返回旧值。(这里借用别人的总结)
    

    https://www.cnblogs.com/houstao/p/8271362.html

    我使用的是jdk11 和jdk8的源码有差异,但原理基本不变

    如有错误,请留言告诉我

  • 相关阅读:
    Picture Control点击事件
    在C/C++中获取可执行文件的图标和信息
    C++获取系统图标方法
    C++ Vector 使用总结
    C++中vector和list的区别
    STL STD::list使用说明
    演示My97 DatePicker过程中的错误
    HTML5的语法变化
    利用 ACE 来实现 UDP 通讯
    VS2010中“工具>选项中的VC++目录编辑功能已被否决”解决方法
  • 原文地址:https://www.cnblogs.com/sm1128/p/11458671.html
Copyright © 2011-2022 走看看