HashMap实现原理

Posted huangxy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap实现原理相关的知识,希望对你有一定的参考价值。

简介

HashMap 根据键的 hashCode 进行数据的存取,大多数情况下可以直接定位到它的值,从而具有很高的效率,是无序的,要想具有顺序可用LinkedHashMap; 键值均可为null;是非线程安全的,如果需要满足线程安全,可以用Collections的synchronizedMap或者使用 ConcurrentHashMap。

JDK1.7实现

技术图片

JDK1.7中HashMap采用数组+链表的实现方式,Entry 是 HashMap 中的一个内部类,他的成员变量包括:key(键)、value(值)、next(用于实现链表结构,指向下一个链表节点)、hash(存放的是当前key的hashCode)。

put方法

public V put(K key, V value) 
        if (table == EMPTY_TABLE)  //是否初始化
            inflateTable(threshold);
        
        if (key == null) //放置在0号位置
            return putForNullKey(value);
        int hash = hash(key); //计算hash值
        int i = indexFor(hash, table.length);  //计算在Entry[]中的存储位置
        for (Entry<K,V> e = table[i]; e != null; e = e.next) 
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            
        

        modCount++;
        addEntry(hash, key, value, i); //添加到Map中
        return null;

在添加键值对时,首先判断table是否初始化,如果没有,则进行初始化;然后判断key是否为null,如果为null,放置在Entry[]的0号位置,不为null,计算在Entry[]数组的存储位置;判断该位置上是否存在元素,如果存在,则遍历该Entry[]数组位置上的链表;判断key是否存在,如果key已经存在,则用新的value值,替换点旧的value值,并将旧的value值返回;将key-vlaue生成Entry实体,添加到HashMap中的Entry[]数组中。

get方法

public V get(Object key) 
     if (key == null)
         //返回table[0] 的value值
         return getForNullKey();
     Entry<K,V> entry = getEntry(key);

     return null == entry ? null : entry.getValue();

final Entry<K,V> getEntry(Object key) 
     if (size == 0) 
         return null;
     

     int hash = (key == null) ? 0 : hash(key);
     for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) 
         Object k;
         if (e.hash == hash &&
             ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
      
     return null;

首先计算hash值,然后调用indexFor()方法得到该key在table中的存储位置,得到该位置的单链表,遍历链表找到key和其对应的Entry,通过entry.value返回value值。

JDK1.8实现

技术图片

在JDK1.8中,HashMap存储的数据结构由数组+链表的方式,变为数组+链表+红黑树的存储方式,提升了性能;解决了JDK1.7版在并发条件下出现死循环的问题。

问题

问:如果两个key的hashCode相同,如何获取值对象? 

答:当调用get方法时,HashMap会使用key的hashCode值,找到bucket位置,因为hashCode相同,bucket会发生碰撞,然后遍历链表,通过key的equals方法找到键值对。

以上是关于HashMap实现原理的主要内容,如果未能解决你的问题,请参考以下文章

为啥面试要问hashmap 的原理

HashMap底层的实现原理

HashMap工作原理及实现

HashMap实现原理及源码分析

HashMap实现原理及源码分析

Hashmap的实现原理