Java中对HashMap的深度分析与比较

在Java的世界里,无论类还是各种数据,其结构的处理是整个程序的逻辑以及性能的关键。由于本人接触了一个有关性能与逻辑同时并存的问题,于是就开始研究这方面的问题。找遍了大大小小的论坛,也把《Java 虚拟机规范》,《apress,.java.collections.(2001),. bm.ocr.6.0.shareconnector》,和《Thinking in Java》翻了也找不到很好的答案,于是一气之下把JDK的 src 解压出来研究,扩然开朗,遂写此文,跟大家分享感受和顺便验证我理解还有没有漏洞。 这里就拿HashMap来研究吧。

HashMap可谓JDK的一大实用工具,把各个Object映射起来,实现了“键--值”对应的快速存取。但实际里面做了些什么呢?

在这之前,先介绍一下负载因子和容量的属性。大家都知道其实一个 HashMap 的实际容量就 因子*容量,其默认值是 16×0.75=12; 这个很重要,对效率很一定影响!当存入HashMap的对象超过这个容量时,HashMap 就会重新构造存取表。这就是一个大问题,我后面慢慢介绍,反正,如果你已经知道你大概要存放多少个对象,最好设为该实际容量的能接受的数字。

两个关键的方法,put和get:

先有这样一个概念,HashMap是声明了 Map,Cloneable, Serializable 接口,和继承了 AbstractMap 类,里面的 Iterator 其实主要都是其内部类HashIterator 和其他几个 iterator 类实现,当然还有一个很重要的继承了 Map.Entry 的 Entry 内部类,由于大家都有源代码,大家有兴趣可以看看这部分,我主要想说明的是 Entry 内部类。它包含了 hash,value,key 和next 这四个属性,很重要。put的源码如下

public Object put(Object key, Object value) {Object k = maskNull(key);

这个就是判断键值是否为空,并不很深奥,其实如果为空,它会返回一个static Object 作为键值,这就是为什么HashMap允许空键值的原因。

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

这连续的两步就是 HashMap 最牛的地方!研究完我都汗颜了,其中 hash 就是通过 key 这个Object的 hashcode 进行 hash,然后通过 indexFor 获得在Object table的索引值。

table???不要惊讶,其实HashMap也神不到哪里去,它就是用 table 来放的。最牛的就是用 hash 能正确的返回索引。其中的 hash算法,我跟JDK的作者 Doug 联系过,他建议我看看《The art of programing vol3》可恨的是,我之前就一直在找,我都找不到,他这样一提,我就更加急了,可惜口袋空空啊!!!

不知道大家有没有留意 put 其实是一个有返回的方法,它会把相同键值的 put 覆盖掉并返回旧的值!如下方法彻底说明了 HashMap 的结构,其实就是一个表加上在相应位置的Entry的链表:

for (Entry e = table[i]; e != null; e = e.next) { if (e.hash == hash & & eq(k, e.key)) {  Object oldvalue = e.value;  e.value = value; //把新的值赋予给对应键值。  e.recordAccess(this); //空方法,留待实现  return oldvalue; //返回相同键值的对应的旧的值。 }}modCount++; //结构性更改的次数addEntry(hash, k, value, i); //添加新元素,关键所在!return null; //没有相同的键值返回}

我们把关键的方法拿出来分析:

void addEntry(int hash, Object key, Object value, int bucketIndex) {table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);

因为 hash 的算法有可能令不同的键值有相同的hash码并有相同的table索引,如:key=“33”和key=Object g的hash都是-8901334,那它经过indexfor之后的索引一定都为i,这样在new的时候这个Entry的next就会指向这个原本的table[i],再有下一个也如此,形成一个链表,和put的循环对定e.next获得旧的值。到这里,HashMap的结构,大家也十分明白了吧?

if (size++ >= threshold) //这个threshold就是能实际容纳的量resize(2 * table.length); //超出这个容量就会将Object table重构

所谓的重构也不神,就是建一个两倍大的table(我在别的论坛上看到有人说是两倍加1,把我骗了),然后再一个个indexfor进去!注意!!这就是效率!!如果你能让你的HashMap不需要重构那么多次,效率会大大提高!

说到这里也差不多了,get比put简单得多,大家,了解put,get也差不了多少了。对于collections我是认为,它是适合广泛的,当不完全适合特有的,如果大家的程序需要特殊的用途,自己写吧,其实很简单。(作者是这样跟我说的,他还建议我用LinkedHashMap,我看了源码以后发现,LinkHashMap其实就是继承HashMap的,然后override相应的方法,有兴趣的同人,自己looklook)建个 Object table,写相应的算法,就ok啦。

举个例子吧,像 Vector,list 啊什么的其实都很简单,最多就多了的同步的声明,其实如果要实现像Vector那种,插入,删除不多的,可以用一个Object table来实现,按索引存取,添加等。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-129985/,如需转载,请注明出处,否则将追究法律责任。

linux hashmap,Java中对HashMap的深度分析与比较相关推荐

  1. java中hashmap_Java HashMap – Java中的HashMap

    java中hashmap Java HashMap is one of the most popular Collection classes in java. Java HashMap is Has ...

  2. [转]为什么Java中的HashMap默认加载因子是0.75

    前几天在一个群里看到有人讨论hashmap中的加载因子为什么是默认0.75. HashMap源码中的加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75 ...

  3. 使用List在Java中的HashMap实现

    HashMap is one of the most widely used implementation of Map to store key-value pairs. It was introd ...

  4. 关于Java中的HashMap的深浅拷贝的测试与几点思考

    0.前言 工作忙起来后,许久不看算法,竟然DFA敏感词算法都要看好一阵才能理解...真是和三阶魔方还原手法一样,田园将芜,非常可惜啊. 在DFA算法中,第一步是需要理解它的数据结构,在此基础上,涉及到 ...

  5. Java 中的 HashMap

    Java 中的 HashMap 作者:Grey 原文地址:Java 中的 HashMap 扩容机制 jdk1.7 先生成新数组. 遍历老数组中的每个位置上的链表上的个元素. 取个元素的key,并基于新 ...

  6. java foreach hashmap_在 Java 中遍历 HashMap 的5种最佳方式

    在本文中,我们将通过示例讨论在 Java 上遍历  HashMap  的五种最佳方式. 使用  Iterator  遍历 HashMap EntrySet 使用  Iterator  遍历 HashM ...

  7. java中实现对象的深度克隆

    1.什么是深度拷贝和浅拷贝 python中有深度拷贝(也可以叫深度克隆)和浅拷贝,同样在java中很多时候需要深度拷贝对象,所谓的深度拷贝对象指的就是对于对象的所用数据及其全部进行copy一份,变成两 ...

  8. Linux的网桥中的STP的实现分析初步

    Linux的网桥中的STP的实现分析初步 本文转自:http://blog.sina.com.cn/s/blog_a3eacdb2010158hn.html 一.STP的框架结构 STP发送的是BPD ...

  9. Java中遍历HashMap的5种方式

    From: https://blog.csdn.net/w605283073/article/details/80708943 本教程将为你展示Java中HashMap的几种典型遍历方式. 如果你使用 ...

最新文章

  1. LintCode 249. 统计前面比自己小的数的个数
  2. Arduino Yun的主要部件介绍选自Arduino Yun快速入门教程
  3. 画单自由度系统传递函数(实频,虚频,幅频,相位,导纳)
  4. ibm3650m2 如何安装linux4,System x3650M2 (Type 7947) Windows Server 2008安装指南
  5. 前端学习(1035):bootstrap-js插件1
  6. R学习-- 数组和矩阵
  7. Yii2.x 互斥锁Mutex-类图
  8. english 2012020601
  9. 1-java学习笔记
  10. python多线程学了多久_Python多线程一学就会!
  11. 80. Session
  12. 法拉克机器人自动怎么调_发那科机器人的简单设置你知道吗
  13. zip分卷压缩的步骤_rar分卷压缩的步骤详解【图文步骤】
  14. macos android大小写,Git(MacOS)区分大小写覆盖问题
  15. java 穷举_java循环穷举
  16. Windows程序的生与死
  17. 26个顶尖战略咨询公司常用分析模型详解!
  18. 说小台芒本可儿傲娇又冷艳,也不看看颜值和身段?
  19. 2021年建5G基站60万个;中兴遭减持;三大运营商2020年成绩单;电信发布新手机...
  20. Mac中iterm2显示彩色

热门文章

  1. Attention 扫盲:注意力机制及其 PyTorch 应用实现
  2. 超越 MobileNet,谷歌提出 MobileDets:移动端目标检测新标杆
  3. 资讯|WebRTC M92 更新
  4. 如何科学地完成一场 AR 发布会?
  5. 电动垂直起降飞机已经完成测试,就差一张飞行执照即可合法升空
  6. 关于MySQL查询优化 の 30条忠告
  7. 《 自动化测试最佳实践:来自全球的经典自动化测试案例解析》一一1.6 正确度量...
  8. 专注于网络安全的数据中心在莫斯科开通运营
  9. 整形数组按照频率排序
  10. zabbix系列(六)zabbix添加对ubuntu系统的监控