HashMap的数据结构

HashMap是一种基于哈希表的数据结构,其table数组每个元素是一个链表头节点。当size达到阈值threshold时,HashMap会进行resize操作,创建新的两倍大小的newTable并将原有元素迁移。在多线程环境下,put操作可能导致resize时的死循环问题。HashMap的get操作通过key的哈希码定位bucket并遍历查找相应entry。其哈希码是所有entry哈希码之和。需要注意的是,HashMap不是线程安全的。

数据结构


  • transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
  • table中的每一个元素是一个链表的头结点,这些链表称为bucket
  • size——HashMap包含的entry个数
  • threshold——触发HashMap.resize的阈值

 

PUT

  1. 通过

        int hash = hash(key);
        int i = indexFor(hash, table.length);

确定key所在bucket

  1. 从头遍历bucket,如果有key相等的entry,则返回oldValue,将原entryvalue置为newValue;如果bucket中没有key相等的entry,则用<key,value>新建entry插入HashMap
  2. 在插入新entry时(之前),HashMap会检查当前size的大小,如果size>=threshold,则执行resize
  3. 插入新entry后返回null

 

GET

  1. 通过 
 <span style="white-space:pre">	</span>int hash = hash(key);
        int i = indexFor(hash, table.length);

确定key所在bucket

  1. 从头遍历bucket,如果有key相等的entry,返回value。否则,返回null

 

RESIZE

resize过程中,程序会新建一个newTable(大小为2*table.length),将table中的entry移动到newTable中(不是简单的移动)。然后将newTable作为table

如果在resize过程中有多个线程在执行HashMap.put,有可能产生一个比较严重的BUG——HashMap.get时发生死循环(参考:http://blog.youkuaiyun.com/yinhesky/article/details/9061497

 

HashCode

The hash code of a map is defined to be the sum of the hash codes ofeach entry in the map's entrySet() view.

 

来自 <http://docs.oracle.com/javase/6/docs/api/java/util/Map.html#hashCode()>

 

线程不安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值