第二个灵魂 发表于 2015-1-18 11:19:15

JAVA教程之Java 8:HashMap的功能提拔仓酷云

还有就是总有人问我到底该学习什么语言,什么语言有前途,那么我的回答是不论是C,C++,java,.net网页编程,ruby,asp或是其他语言都可以学,编程的关键不是语言,而是思想。HashMap
这些工具你应当都已晓得了。你大概还晓得哈希碰撞会对hashMap的功能带来劫难性的影响。假如多个hashCode()的值落到统一个桶内的时分,这些值是存储到一个链表中的。最坏的情形下,一切的key都映照到统一个桶中,如许hashmap就退步成了一个链表——查找工夫从O(1)到O(n)。我们先来测试下一般情形下hashmap在Java7和Java8中的体现。为了能完成把持hashCode()办法的举动,我们界说了以下的一个Key类:

classKeyimplementsComparable<Key>{privatefinalintvalue;Key(intvalue){this.value=value;}@OverridepublicintcompareTo(Keyo){returnInteger.compare(this.value,o.value);}@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;Keykey=(Key)o;returnvalue==key.value;}@OverridepublicinthashCode(){returnvalue;}}
Key类的完成中规中矩:它重写了equals()办法而且供应了一个还算过得往的hashCode()办法。为了不过分的GC,我将不成变的Key对象缓存了起来,而不是每次都从头入手下手创立一遍:

classKeyimplementsComparable<Key>{publicclassKeys{publicstaticfinalintMAX_KEY=10_000_000;privatestaticfinalKey[]KEYS_CACHE=newKey;static{for(inti=0;i<MAX_KEY;++i){KEYS_CACHE=newKey(i);}}publicstaticKeyof(intvalue){returnKEYS_CACHE;}}
如今我们能够入手下手举行测试了。我们的基准测试利用一连的Key值来创立了分歧的巨细的HashMap(10的乘方,从1到1百万)。在测试中我们还会利用key来举行查找,并丈量分歧巨细的HashMap所消费的工夫:

importcom.google.caliper.Param;importcom.google.caliper.Runner;importcom.google.caliper.SimpleBenchmark;publicclassMapBenchmarkextendsSimpleBenchmark{privateHashMap<Key,Integer>map;@ParamprivateintmapSize;@OverrideprotectedvoidsetUp()throwsException{map=newHashMap(mapSize);for(inti=0;i<mapSize;++i){map.put(Keys.of(i),i);}}publicvoidtimeMapGet(intreps){for(inti=0;i<reps;i++){map.get(Keys.of(i%mapSize));}}}

成心思的是这个复杂的HashMap.get()内里,Java8比Java7要快20%。全体的功能也相称不错:只管HashMap里有一百万笔记录,单个查询也只花了不到10纳秒,也就是也许我呆板上的也许20个CPU周期。相称使人震动!不外这并非我们想要丈量的方针。
假定有一个很低劣的key,他老是前往统一个值。这是最糟的场景了,这类情形完整就不该该利用HashMap:

classKeyimplementsComparable<Key>{//...@OverridepublicinthashCode(){return0;}}

Java7的了局是意料中的。跟着HashMap的巨细的增加,get()办法的开支也愈来愈年夜。因为一切的纪录都在统一个桶里的超长链表内,均匀查询一笔记录就必要遍历一半的列表。因而从图上能够看到,它的工夫庞大度是O(n)。
不外Java8的体现要好很多!它是一个log的曲线,因而它的功能要好上好几个数目级。只管有严峻的哈希碰撞,已经是最坏的情形了,但这个一样的基准测试在JDK8中的工夫庞大度是O(logn)。独自来看JDK8的曲线的话会更分明,这是一个对数线性散布:

为何会有这么年夜的功能提拔,只管这里用的是年夜O标记(年夜O形貌的是渐近上界)?实在这个优化在JEP-180中已提到了。假如某个桶中的纪录过年夜的话(以后是TREEIFY_THRESHOLD=8),HashMap会静态的利用一个专门的treemap完成来交换失落它。如许做的了局会更好,是O(logn),而不是糟的O(n)。它是怎样事情的?后面发生抵触的那些KEY对应的纪录只是复杂的追加到一个链表前面,这些纪录只能经由过程遍向来举行查找。可是凌驾这个阈值后HashMap入手下手将列表晋级成一个二叉树,利用哈希值作为树的分支变量,假如两个哈希值不等,但指向统一个桶的话,较年夜的谁人会拔出到右子树里。假如哈希值相称,HashMap但愿key值最好是完成了Comparable接口的,如许它能够依照按次来举行拔出。这对HashMap的key来讲并非必需的,不外假如完成了固然最好。假如没有完成这个接口,在呈现严峻的哈希碰撞的时分,你就并别期望能取得功能提拔了。

而学习JAVA我觉得最应该避免的就是:只学习,不思考,只记忆,不实践!

乐观 发表于 2015-1-19 23:05:54

如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。

老尸 发表于 2015-1-25 08:21:23

是一种使网页(Web Page)产生生动活泼画面的语言

若天明 发表于 2015-1-31 06:39:15

其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。

爱飞 发表于 2015-2-1 10:07:10

Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。

再现理想 发表于 2015-2-5 15:52:55

关于设计模式的资料,还是向大家推荐banq的网站 http://www.jdon.com/,他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。

海妖 发表于 2015-2-10 01:45:18

还好,SUN提供了Javabean可以把你的JSP中的 Java代码封装起来,便于调用也便于重用。

分手快乐 发表于 2015-2-16 09:42:37

任职于太阳微系统的詹姆斯·高斯林等人于1990年代初开发Java语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的程序语言

透明 发表于 2015-2-28 23:30:27

任职于太阳微系统的詹姆斯·高斯林等人于1990年代初开发Java语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的程序语言

蒙在股里 发表于 2015-3-10 10:30:20

如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。

变相怪杰 发表于 2015-3-17 06:11:20

至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail 了。

谁可相欹 发表于 2015-3-17 06:11:20

有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想)

若相依 发表于 2015-3-23 23:08:35

如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。
页: [1]
查看完整版本: JAVA教程之Java 8:HashMap的功能提拔仓酷云