码迷,mamicode.com
首页 > 其他好文 > 详细

HashMap实现原理

时间:2019-07-07 09:17:40      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:实现原理   ||   hashcode   mamicode   包括   code   try   inflate   inf   

简介

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实现原理

标签:实现原理   ||   hashcode   mamicode   包括   code   try   inflate   inf   

原文地址:https://www.cnblogs.com/huangxy/p/11143204.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!