在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来实现,按索引存取,添加等。
如果插入,删除比较多的,可以建两个Object table,然后每个元素用含有next结构的,一个table存,如果要插入到i,但是i已经有元素,用next连起来,然后size++,并在另一个table记录其位置。
分享到:
相关推荐
免费的防止锁屏小软件,可用于域统一管控下的锁屏机制
内容概要:本文介绍了一段简单的Python代码,用于在控制台中输出一棵带有装饰的圣诞树。具体介绍了代码结构与逻辑,包括如何计算并输出树形的各层,如何加入装饰元素以及打印树干。还提供了示例装饰字典,允许用户自定义圣诞树装饰位置。 适用人群:所有对Python编程有一定了解的程序员,尤其是想要学习控制台图形输出的开发者。 使用场景及目标:适用于想要掌握如何使用Python代码创建控制台艺术,特别是对于想要增加节日氛围的小项目。目标是帮助开发者理解和实现基本的字符串操作与格式化技巧,同时享受创造乐趣。 其他说明:本示例不仅有助于初学者理解基本的字符串处理和循环机制,而且还能激发学习者的编程兴趣,通过调整装饰物的位置和树的大小,可以让输出更加个性化和丰富。
白色大气风格的设计师作品模板下载.zip
电商平台开发需求文档.doc
白色简洁风格的办公室室内设计门户网站模板下载.zip
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
课程设计---基于Android stduio的手机银行开发与设计 现今,手机已经成为人们生活和工作的必备品,在手机各种系统中Android系统是人们用的比较多的系统。手机银行也是人们在生活中比较常用的功能之一。本项目基于Android的手机银行开发与设计主要功能有登录注册、转账、转账记录查询、修改及查询个人信息、添加好友、向好友转账的功能。本项目主要用Android Studio 开发,数据库SQLite数据库,和夜神模拟器。 基于Android stduio的手机银行开发与设计项目主要功能有登录注册、转账、转账记录查询、修改及查询个人信息、添加好友、向好友转账的功能。。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
白色大气风格的婚礼现场倒计时模板下载.zip
轮式移动机器人轨迹跟踪的MATHLAB程序,运用运动学和动力学模型的双闭环控制,借鉴自抗扰控制技术结合了非线性ESO,跟踪效果良好,控制和抗扰效果较优,可分享控制结构图。 这段程序主要是一个小车的动力学仿真程序,用于模拟小车在参考轨迹下的运动。下面我将对程序进行详细的分析解释。 首先,程序开始时使用`clear`、`clc`和`close all`命令来清除工作空间、命令窗口和图形窗口中的内容。 接下来,程序定义了一系列参数和变量,用于设置仿真的参数和存储仿真过程中的数据。这些参数包括小车的质量、车宽、驱动轮半径等,还有参考轨迹的振幅和频率,仿真步长,仿真时间等。 然后,程序定义了一些元胞数组,用于存储不同阶段的数据。这些数组包括参考轨迹位姿、真实运动轨迹位姿、参考轨迹一阶导数、参考轨迹速度、期望速度、真实速度、控制器输出的控制力矩、控制输入、期望速度与真实速度误差、摩擦值、外界扰动值、总扰动、位姿跟踪误差、扰动观测值等。 接下来,程序给这些变量赋初始值,包括小车的初始位姿和速度,初始速度,期望初始速度,控制器输出的控制力矩,扰动观测值等。 然后,程序进入一个循环,仿真时间从
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
这是一份来自开源的全球新冠肺炎数据集,每日时间序列汇总,包括确诊、死亡和治愈。所有数据来自每日病例报告。数据持续更新中。 由于数据集中没有美国的治愈数据,所以在统计全球的现有确诊人员和治愈率的时候会有很大误差,代码里面先不做这个处理,期待数据集的完善。
白色大气风格的时装设计公司模板下载.zip
白色大气风格的商务会议活动模板下载.rar
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;
本次开发一套基于微信小程序的生签到系统,有管理员,教师,学生三个角色。管理员功能有个人中心,学生管理,教师管理,签到管理,学生签到管理,班课信息管理,加入班课管理,请假信息管理,审批信息管理,销假信息管理,系统管理。教师和学生都可以在微信端注册和登录,教师可以管理签到信息,管理班课信息,审批请假信息,查看学生签到,查看加入班级,查看审批信息和销假信息。学生可以查看教师发布的学生签到信息,可以自己选择加入班课信息,添加请假信息,查看审批信息,进行销假操作。基于微信小程序的生签到系统服务端用Java开发的网站后台,接收并且处理微信小程序端传入的json数据,数据库用到了MySQL数据库作为数据的存储。
**脚本描述**:本脚本围绕着新年这个充满欢乐与希望的时刻展开。故事发生在一个热闹的小镇,主要角色有在外打拼多年的年轻人小李,他的父母,以及一群充满活力的小镇居民。新年将至,小李踏上回家的旅途,满心期待与家人团聚。在小镇上,大家都在积极筹备新年,贴春联、挂灯笼、准备年夜饭。小李与家人重逢后,一起分享着彼此的故事和喜悦。同时,他们也和小镇居民一起举办了热闹的庆祝活动,在欢声笑语中迎接新年的到来。这个新年不仅让小李重新感受到了家的温暖,也让他对未来充满了信心和希望,他决定和小镇一起成长发展。通过这个脚本,展现新年带给人们的幸福、温暖和对未来的憧憬。
Python 自动办公- Python分类汇总278张Excel表中的数据
白色创意风格的用户信息登记源码下载.zip
白色大气的音乐专辑博客整站网站模板下载.zip