仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3079|回复: 19
打印 上一主题 下一主题

[学习教程] JAVA网页编程之Java中对HashMap的深度剖析与对照

[复制链接]
山那边是海 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:30:37 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
C#跟java类似,但是在跨平台方面理论上可以跨平台,实际上应用不大,执行性能优于java,跟C++基本一致,但是启动速度还是慢.代码安全,但容易性能陷阱.对照在Java的天下里,不管类仍是各类数据,其布局的处置是全部程序的逻辑和功能的关头。因为自己打仗了一个有关功能与逻辑同时并存的成绩,因而就入手下手研讨这方面的成绩。找遍了年夜巨细小的论坛,也把《Java假造机标准》,《apress,.java.collections.(2001),.bm.ocr.6.0.shareconnector》,和《ThinkinginJava》翻了也找不到很好的谜底,因而一气之下把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的源码以下

publicObjectput(Objectkey,Objectvalue){
Objectk=maskNull(key);

  这个就是判别键值是不是为空,其实不很深邃,实在假如为空,它会前往一个staticObject作为键值,这就是为何HashMap同意空键值的缘故原由。

inthash=hash(k);
inti=indexFor(hash,table.length);

  这一连的两步就是HashMap最牛的中央!研讨完我都汗颜了,个中hash就是经由过程key这个Object的hashcode举行hash,然后经由过程indexFor取得在Objecttable的索引值。

  table???不要惊奇,实在HashMap也神不到那里往,它就是用table来放的。最牛的就是用hash能准确的前往索引。个中的hash算法,我跟JDK的作者Doug接洽过,他倡议我看看《Theartofprogramingvol3》可爱的是,我之前就一向在找,我都找不到,他如许一提,我就加倍急了,惋惜口袋空空啊!!!

  不晓得人人有无寄望put实际上是一个有前往的办法,它会把不异键值的put掩盖失落并前往旧的值!以下办法完全申明了HashMap的布局,实在就是一个表加上在响应地位的Entry的链表:

for(Entrye=table[i];e!=null;e=e.next){
 if(e.hash==hash&&eq(k,e.key)){
  Objectoldvalue=e.value;
  e.value=value;//把新的值付与给对应键值。
  e.recordAccess(this);//空办法,留待完成
  returnoldvalue;//前往不异键值的对应的旧的值。
 }
}
modCount++;//布局性变动的次数
addEntry(hash,k,value,i);//增加新元素,关头地点!
returnnull;//没有不异的键值前往
}

  我们把关头的办法拿出来剖析:

voidaddEntry(inthash,Objectkey,Objectvalue,intbucketIndex){
table[bucketIndex]=newEntry(hash,key,value,table[bucketIndex]);

  由于hash的算法有大概令分歧的键值有不异的hash码并有不异的table索引,如:key=“33”和key=Objectg的hash都是-8901334,那它经由indexfor以后的索引必定都为i,如许在new的时分这个Entry的next就会指向这个底本的table[i],再有下一个也云云,构成一个链表,和put的轮回对定e.next取得旧的值。到这里,HashMap的布局,人人也非常分明了吧?

if(size++>=threshold)//这个threshold就是能实践包容的量
resize(2*table.length);//超越这个容量就会将Objecttable重构

  所谓的重构也不神,就是建一个两倍年夜的table(我在其余论坛上看到有人说是两倍加1,把我骗了),然后再一个个indexfor出来!注重!!这就是效力!!假如你能让你的HashMap不必要重构那末屡次,效力会年夜年夜进步!

  说到这里也差未几了,get比put复杂很多,人人,懂得put,get也差不了几了。关于collections我是以为,它是合适普遍的,当不完整合适独有的,假如人人的程序必要特别的用处,本人写吧,实在很复杂。(作者是如许跟我说的,他还倡议我用LinkedHashMap,我看了源码今后发明,LinkHashMap实在就是承继HashMap的,然后override响应的办法,有乐趣的同人,本人looklook)建个Objecttable,写响应的算法,就ok啦。

  举个例子吧,像Vector,list啊甚么的实在都很复杂,最多就多了的同步的声明,实在假如要完成像Vector那种,拔出,删除未几的,能够用一个Objecttable来完成,按索引存取,增加等。

  假如拔出,删除对照多的,能够建两个Objecttable,然后每一个元素用含有next布局的,一个table存,假如要拔出到i,可是i已有元素,用next连起来,然后size++,并在另外一个table纪录其地位。




对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net也不过3,4本书足以,这就是区别。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-25 09:07

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表