Java HashMap的工作原理.docxVIP

  1. 1、本文档共14页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Java HashMap的工作原理这篇文章主要介绍了Java HashMap的工作原理的相关资料,需要的朋友可以参考下大部分Java开发者都在使用Map,特别是HashMap。HashMap是一种简单但强大的方式去存储和获取数据。但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.HashMap的大量源代码(包括Java 7 和Java 8),来深入理解这个基础的数据结构。在这篇文章中,我会解释java.util.HashMap的实现,描述Java 8实现中添加的新特性,并讨论性能、内存以及使用HashMap时的一些已知问题。内部存储Java HashMap类实现了Map<K, V>接口。这个接口中的主要方法包括:1234V put(K key, V value)V get(Object key)V remove(Object key)Boolean containsKey(Object key)HashMap使用了一个内部类Entry<K, V>来存储数据。这个内部类是一个简单的键值对,并带有额外两个数据:一个指向其他入口(译者注:引用对象)的引用,这样HashMap可以存储类似链接列表这样的对象。一个用来代表键的哈希值,存储这个值可以避免HashMap在每次需要时都重新生成键所对应的哈希值。下面是Entry<K, V>在Java 7下的一部分代码:1234567static class Entry<K,V> implements Map.Entry<K,V> {final K key;V value;Entry<K,V> next;int hash;…}HashMap将数据存储到多个单向Entry链表中(有时也被称为桶bucket或者容器orbins)。所有的列表都被注册到一个Entry数组中(Entry<K, V>[]数组),这个内部数组的默认长度是16。下面这幅图描述了一个HashMap实例的内部存储,它包含一个nullable对象组成的数组。每个对象都连接到另外一个对象,这样就构成了一个链表。所有具有相同哈希值的键都会被放到同一个链表(桶)中。具有不同哈希值的键最终可能会在相同的桶中。当用户调用 put(K key, V value) 或者 get(Object key) 时,程序会计算对象应该在的桶的索引。然后,程序会迭代遍历对应的列表,来寻找具有相同键的Entry对象(使用键的equals()方法)。对于调用get()的情况,程序会返回值所对应的Entry对象(如果Entry对象存在)。对于调用put(K key, V value)的情况,如果Entry对象已经存在,那么程序会将值替换为新值,否则,程序会在单向链表的表头创建一个新的Entry(从参数中的键和值)。桶(链表)的索引,是通过map的3个步骤生成的:首先获取键的散列码。程序重复散列码,来阻止针对键的糟糕的哈希函数,因为这有可能会将所有的数据都放到内部数组的相同的索引(桶)上。程序拿到重复后的散列码,并对其使用数组长度(最小是1)的位掩码(bit-mask)。这个操作可以保证索引不会大于数组的大小。你可以将其看做是一个经过计算的优化取模函数。下面是生成索引的源代码:1234567891011121314// the "rehash" function in JAVA 7 that takes the hashcode of the keystatic int hash(int h) {h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);}// the "rehash" function in JAVA 8 that directly takes the keystatic final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}// the function that returns the index from the rehashed hashstatic int indexFor(int h, int length) {return h & (length-1);}为了更有效地工作,内部数组的大小必须是2的幂值。让我们看一下为什么:假设数组的长度是17,那么掩码的值就是16(数组长度-1)。16的二进制表示是0…010000,这样对于任何值H来说,“H & 16”的结果就是16或者0。这意味着长度为17的数组只能应用到两个桶上:一个是0,另外一个是16,这样不是很有效率。但是如果你将数组的长度设置为2的幂值,例如

文档评论(0)

visa158 + 关注
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档