谈到hashMap对象时,我想大部分的java开发人员头脑里面马上会蹦出这么一个植入骨髓的概念:
键值对,即我们通常所说的key-value。
没错,key-value的理解是正确的。倘若有人问你:key、value是如何存取的呢?
通常我们的回答是:通过key值,直接获取返回的value值啊!
倘若别人继续问你:如何通过key来获取一个value对象,key值又是如何生成以及存储的?
我想好多人都无从回答了。
下面我们简单分析下,map中的key和value的存取规则,看看和你之前的理解有何出入,写的不对的地方,希望各位大拿积极指点:
下面看下hashMap实现的数据结构:
在本文中,我们不关注java源码是怎么实现整个过程的,我们只关注它的实现原理。从上图中我们可以看到,图片的上方是一个很明显的数据类型(table[]),在数组的某些位置,会向下延伸出一些元素,它看起来是不是很像一个link链表呢?没错,它就是一个list链表。这就是hashtable的数据结构。说到这儿,可能有人迷糊了,hashTable不是键值对么,key值不是唯一的么,通过一个数组如何确认和定位呢?下面我详细介绍下:
HashMap结构 = 一维数组(一维数组里面的元素可以是list链表)
大家可能对上面的数据结构犯晕了,没事,看我下面这段解释就清楚了。从事java开发的人都知道,hashMap跟放入key值的对象的hashcode方法相关。因为hashMap是通过hash码的方式进行数据的快速定位。而hash码是根据hashcode方法生成的。
假设我们有一个数组table[];
我们还有一个专门用来存放键值对的对象entity<key,value>;
Table数组里面存放的就是键值对对象引用entity<key,value>,那么为什么说haspmap取值速度很快呢,原因就在于前面提到的hash码,我们可以通过hash码来获取对于的entity<key,value>,既然entity<key,value>是放入table[]数组对象的,那么就不能想象:莫非hash码就是table[]数组的下标值。事实的确如此。让我们来分析如下一段代码,来分析下hashMap的存取过程:
Map<String ,String> map = newHashMap<String,Sting>();
map.put(“wang”,”男“);
我们假定hashMap中Table[]数组的初始长度是16,那么首先是创建:
Table[]tables = new Table[16];
然后将key-value值放入entity对象,entity对象中存在对key和value值的存取方法,然后将entity对象放入tables数组,可是该放入数组的什么位置呢,是按照顺序存储?还是随机存储?前面提到过,hashcode方法生成hash码就是我们对应的数组下标的位置,例如我们“wang“这个字符串如果生成的hash码为8,则对应我们的entity对象存储位置为:
tables[8] = entity1;
写到这儿,大家知道为什么hashMap取值的时候为什么这么快了吧,因为我在取值的时候先根据key值生成hash码8,直接去数组里面找索引为8的对象,没有数据的检索扫描,当然快了。
不知道大家有没有这样的疑问,既然key值至少为了生成hash码,那为什么还要存储entity对象中呢?
这个其实在hashMap数据结构中其实已经有所体现了,大家看到数据对象其实可以是一个list链表集合。这是因为不同的对象、或者hashMap中定义的数组大小已经被沾满,那么hash码就是产生重复,就是出现如下情况:
我们接着上面的例子:
map.put(obj,”汽车对象“);
假如说obj是一个自定义的对象,二hashcode方法产生的hash码恰好也是8,那么,table数组将会是如下:
Listlist = new LinkedList();
list.add(entity1);//”wang”,”男”键值对
list.add(entity2);//obj和汽车对象
Table[8] = list;
当我们通过map.get(obj)来获取汽车对象时,首先根据hash码8找到list,然后再遍历list里面的key值,通过key值的equals()方法进行比较,如果相等,则返回entity2里面的vale值,示意程序如下:
Listlist = table[8];//通过hash码获取索引位置
For(Entity o :list){//遍历suolist
o.key.equals(obj){//通过map.get里面的key同Entity里面的key进行比较
return o.value;//返回vale值
}
}
如果map里面存储了大量的对象,那么也就是说hash码的重复值回越来越多,重复值越多,数组里面的linklist元素越多,需要经过大量的遍历和判断,程序性能就是越来越差。下一次我将把我对hashMap的性能优化的理解进行总结。