您的位置:首页 > 编程语言 > Java开发

理解Java中的hashmap

2012-10-25 11:02 288 查看
首先 HashMap里面实现一个静态内部类 Entry 其重要的属性有 key
, value, next,从属性 key,value我们就能很明显的看出来 Entry就是HashMap 键值对实现的一个基础 bean,我们上面说到HashMap的基 础就是一个线性数组,这个数组就是 Entry[],Map 里面的内容都保存在 Entry[]里面。
[align=justify]java是这样计算hash值的:根据对象的hashcode计算[/align]

int i
= hash(paramK.hashCode());
[align=left]整个put过程如下:[/align]

public V
put(K paramK, V paramV)
[align=left] {[/align]
if (paramK
== null)
[align=left] return putForNullKey(paramV);[/align]
int i
= hash(paramK.hashCode());
int j
= indexFor(i, this.table.length);//搜索指定hash值在对应table中的索引
for (Entry
localEntry = this.table [j];
localEntry != null; localEntry = localEntry.next )
[align=left] {[/align]
if (localEntry. hash ==
i) { java.lang.Object localObject1;
if (((localObject1
= localEntry.key ) == paramK) || (paramK.equals(localObject1))) {
java.lang.Object localObject2 =
localEntry.value;
localEntry. value =
paramV;
[align=left] localEntry.recordAccess( this);[/align]
[align=left] return localObject2;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
this. modCount +=
1;
[align=left] addEntry(i, paramK, paramV, j);[/align]
[align=left] return null;[/align]
[align=left] }[/align]
[align=left]for循环是判断hash中是不是已经存在了这个key/value,如果已经存在,则更新value的值。[/align]

[align=left]Entry对象中有一个next属性,指向下一个对象。意思是说,如果出现冲突,那么java中实现hashmap的时候是用链表的方式来解决冲突的。[/align]

[align=left]------------------------------[/align]

void addEntry( int paramInt1,
K paramK, V paramV, int paramInt2)
[align=left] {[/align]
[align=left] Entry localEntry = this.table [paramInt2];[/align]
this. table[paramInt2]
= new Entry(paramInt1 ,
paramK, paramV, localEntry);
if ( this.size ++
>= this. threshold)
[align=left] resize(2 * this.table .length );[/align]
[align=left] }[/align]
[align=left]这段代码是增加一个key/value到map中的。其中resize函数是每次增长原来长度的两倍。[/align]
[align=left]其中resize函数中调用了一个名叫transfer的函数,这个函数的作用是对象在数组中的移动。因为resize的时候是新申请一个数组,然后将原来数组中的内容拷贝到新数组中。【拷贝过程涉及到同一个hash值的链表的拷贝】[/align]
[align=left]----------------------------------[/align]

public V get(java.lang.Object
paramObject)
[align=left] {[/align]
if (paramObject
== null)
[align=left] return getForNullKey();[/align]
int i
= hash(paramObject.hashCode());
[align=left] Entry localEntry = this.table [indexFor(i, this.table .length )];[/align]
for (;
localEntry != null;
[align=left] localEntry = localEntry. next)[/align]
[align=left] {[/align]
if (localEntry. hash ==
i) { java.lang.Object localObject;
if (((localObject
= localEntry.key ) == paramObject) || (paramObject.equals(localObject)))
[align=left] return localEntry.value ;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] return null;[/align]
[align=left] }[/align]
[align=left]get函数如上。[/align]
[align=left]在get的时候,需要对那个链表进行遍历,找到hash值的位置之后,对这个链表中的所有元素进行key的对比,当hash值相等并且key相等的时候,就找到了相应的对象。这就是为什么Entry中还要存储key的原因了:因为要处理冲突,而处理冲突的时候是需要对比key的,所以需要存储这个key值。[/align]
[align=left]-------------------[/align]

HashMap():构建一个初始容量为 16,负载因子为 0.75 的 HashMap。
--------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: