Java Collections---HashMap深度分析与比较

原创 2004年08月16日 11:57:00

 

            Java Collections---HashMap深度分析与比较

 


文章声明,本文章完全是本人原创,当鉴于水平有限,如有错误,请各位同人指正!感谢万分!
  在Java的世界里,无论类还是各种数据,其结构的处理是整个程序的逻辑以及性能的关键。由于本人接触了一个有关性能与逻辑同时并存的问题,于是就开始研究这方面的问题。找遍了大大小小的论坛,也把《Java 虚拟机规范》,《apress,.java.collections.(2001),.bm.ocr.6.0.shareconnector》,和《Think 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》可恨的是,我之前就一直在找,我都找不到,他这样一提,我就更加急了,可惜口袋空空啊~~5555


    不知道大家有没有留意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啦。
举个例子吧,像Vertor,list啊什么的其实都很简单,最多就多了的同步的声明,
其实如果要实现像Vector那种,插入,删除不多的,可以用一个Object table来实现,按索引存取,添加等。
如果插入,删除比较多的,可以建两个Object table,然后每个元素用含有next结构的,一个table存,如果要插入到i,但是i已经有元素,用next连起来,然后size++,并在另一个table记录,其位置。


好了,本次是小弟第一次发表技术文章,感谢大家,希望有错的给我当面指正,小弟的面皮特厚,有兴趣的朋友可以联系小弟
QQ:5167822
Email:_gtm_@163.com

   

 

 

 

 

 

 

java深度问题

原文地址:http://www.codeceo.com/article/20-java-interview-questions-from-investment-banks.html 问题一:在多...
  • magic_hwz
  • magic_hwz
  • 2016年05月05日 16:48
  • 420

Java常用容器比较分析

Java常用容器比较分析
  • fumier
  • fumier
  • 2015年04月24日 14:02
  • 977

系统学习深度学习(七)--主流深度学习开源框架对比

转自:http://blog.csdn.net/u010167269/article/details/51810613,本文做了相关修改。 参考论文:《Comparative Study of De...
  • App_12062011
  • App_12062011
  • 2017年01月23日 11:05
  • 5334

深度分析 Java 的 ClassLoader 机制(源码级别)

Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,JVM在加载类的时候,都是通过ClassLoader的l...
  • Jason_huzhe
  • Jason_huzhe
  • 2016年05月05日 09:39
  • 625

各种流行深度学习构架的性能对比

知乎上对各种深度学习方法的对比:         在众多的神经网络框架如chainer, caffe, torch,mxnet等之间如何做选择? 四个月前就有人提出更新对比,现在我看还没有对比更新过。...
  • wishchin
  • wishchin
  • 2016年07月07日 19:34
  • 5573

深度学习和拓扑数据分析的六大惊人之举

摘要:将深度学习与拓扑数据分析相结合,把数据都放到一张图里,可以像观察地图一样观察数据,进而来发现事物的本质。 假如你有一个一千列和一百万行的数据集。无论你从哪个角度看它——小型,中型或大型...
  • u012556077
  • u012556077
  • 2016年01月28日 19:11
  • 650

深度学习笔记——情感分析

本文使用三种深度学习方法对IMDB评论进行情感分析。这三种方法为:MLP、BiRNN(LSTM、GRU)、BiGRU+Attention。...
  • mpk_no1
  • mpk_no1
  • 2017年05月11日 22:14
  • 1411

Java 总结:各种排序算法的介绍及其之间的对比差异

一、概述内部排序:只使用内存。 插入排序:直接插入排序,希尔排序 选择排序:简单选择排序,堆排序 交换排序:冒泡排序,快速排序 归并排序 基数排序 外部排序:内存和外存结合使用。会调用到的代码: ...
  • u014136472
  • u014136472
  • 2015年10月19日 18:26
  • 10472

深度学习几大主流框架的对比

简介 文档与性能 网络与模型能力 生态与维护 框架搭建与应用 架构 1 TensorFlow 2 Caffe 3 MXNet 4 Paddle 5 CNTK 总结 1.简介2.文档与性能3.网络与模型...
  • eternity1118_
  • eternity1118_
  • 2017年05月03日 17:29
  • 1511

C++的继承和Java继承的比较

在C++中继承可分为公有继承(public)保护继承(protected)和私有继承(private),而在Java中默认只有一种继承(相当于C++中的公有继承)下面我们来看一段代码#include ...
  • lxq_xsyu
  • lxq_xsyu
  • 2014年12月14日 14:23
  • 2256
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java Collections---HashMap深度分析与比较
举报原因:
原因补充:

(最多只允许输入30个字)