Java源码分析HashTable源码分析Word文件下载.docx

上传人:b****4 文档编号:6627246 上传时间:2023-05-07 格式:DOCX 页数:14 大小:20.05KB
下载 相关 举报
Java源码分析HashTable源码分析Word文件下载.docx_第1页
第1页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第2页
第2页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第3页
第3页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第4页
第4页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第5页
第5页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第6页
第6页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第7页
第7页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第8页
第8页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第9页
第9页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第10页
第10页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第11页
第11页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第12页
第12页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第13页
第13页 / 共14页
Java源码分析HashTable源码分析Word文件下载.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Java源码分析HashTable源码分析Word文件下载.docx

《Java源码分析HashTable源码分析Word文件下载.docx》由会员分享,可在线阅读,更多相关《Java源码分析HashTable源码分析Word文件下载.docx(14页珍藏版)》请在冰点文库上搜索。

Java源码分析HashTable源码分析Word文件下载.docx

publicHashtable(){

this(11,0.75f);

}

publicHashtable(intinitialCapacity){

this(initialCapacity,0.75f);

publicHashtable(intinitialCapacity,floatloadFactor){

if(initialCapacity<

0)

thrownewIllegalArgumentException("

IllegalCapacity:

"

+

initialCapacity);

if(loadFactor<

=0||Float.isNaN(loadFactor))

IllegalLoad:

+loadFactor);

if(initialCapacity==0)

initialCapacity=1;

this.loadFactor=loadFactor;

table=newEntry[initialCapacity];

threshold=(int)Math.min(initialCapacity*loadFactor,MAX_ARRAY_SIZE+1);

useAltHashing=sun.misc.VM.isBooted()&

&

(initialCapacity>

=Holder.ALTERNATIVE_HASHING_THRESHOLD);

publicHashtable(Map<

?

extendsK,?

extendsV>

t){

this(Math.max(2*t.size(),11),0.75f);

putAll(t);

构造函数和HashMap一样,不同点在于默认容量不一样,HashTable的默认容量是11

hash函数

transientfinalinthashSeed=sun.misc.Hashing.randomHashSeed(this);

privateinthash(Objectk){

if(useAltHashing){

if(k.getClass()==String.class){

returnsun.misc.Hashing.stringHash32((String)k);

}else{

inth=hashSeed^k.hashCode();

//ThisfunctionensuresthathashCodesthatdifferonlyby

//constantmultiplesateachbitpositionhaveabounded

//numberofcollisions(approximately8atdefaultloadfactor).

h^=(h>

>

20)^(h>

12);

returnh^(h>

7)^(h>

4);

}

returnk.hashCode();

hash的计算和HashMap是一样的

判断是否存在给定值

publicsynchronizedbooleancontains(Objectvalue){

if(value==null){

thrownewNullPointerException();

Entrytab[]=table;

for(inti=tab.length;

i-->

0;

){

for(Entry<

e=tab[i];

e!

=null;

e=e.next){

if(e.value.equals(value)){

returntrue;

returnfalse;

publicbooleancontainsValue(Objectvalue){

returncontains(value);

可以看到这里一旦发现value是null就直接抛出异常,这样直接说明HashTable是不允许null-value的。

另外该方法虽然是contains(),但是实际功能和containsValue()是一样的,从containsValue()的实现可以看出

给定的key是否存在

publicsynchronizedbooleancontainsKey(Objectkey){

inthash=hash(key);

intindex=(hash&

0x7FFFFFFF)%tab.length;

e=tab[index];

if((e.hash==hash)&

e.key.equals(key)){

当且仅当给定的key是存在的时候才返回true,但是注意一点的是这里所说的是否存在是取决于equals()方法是如何实现的。

这和开头所强调的存入HashTable的key必须实现hashCode和equals方法是一致的.这里(hash&

0x7FFFFFFF)的目的应该是为了保证hash是一个正值,毕竟只有第32位为0其他都是1

使用给定的key查找

publicsynchronizedVget(Objectkey){

returne.value;

returnnull;

同HashMap,因为这里的底层实现结构都是一样的,都是基于数组,数组的每个下标对应一个单链表。

如果对应的key在HashTable中存在着对应的value那么返回找到的value,否则返回Null

扩容

protectedvoidrehash(){

intoldCapacity=table.length;

Entry<

[]oldMap=table;

//overflow-consciouscode

intnewCapacity=(oldCapacity<

<

1)+1;

if(newCapacity-MAX_ARRAY_SIZE>

0){

if(oldCapacity==MAX_ARRAY_SIZE)

//KeeprunningwithMAX_ARRAY_SIZEbuckets

return;

newCapacity=MAX_ARRAY_SIZE;

[]newMap=newEntry[newCapacity];

modCount++;

threshold=(int)Math.min(newCapacity*loadFactor,MAX_ARRAY_SIZE+1);

booleancurrentAltHashing=useAltHashing;

(newCapacity>

booleanrehash=currentAltHashing^useAltHashing;

table=newMap;

for(inti=oldCapacity;

old=oldMap[i];

old!

){

e=old;

old=old.next;

if(rehash){

e.hash=hash(e.key);

intindex=(e.hash&

0x7FFFFFFF)%newCapacity;

e.next=newMap[index];

newMap[index]=e;

当实际装入的键值对的个数超过了table的长度也就是容量capacity和装载因子的乘积,就会进行扩容,扩容过程是自动的,但是比较耗时。

扩增后的容量是最初的容量的2倍加1,这里和HashMap对比就很容易理解,HashMap的初始容量是偶数,而且要求容量一直是偶数,那么扩容的时候就直接扩大到原来的2倍。

相应的,HashTable的初始容量是奇数11,2倍之后变成偶数,所以加1。

不过这里没有要求HashTable的容量必须是奇数,但无论如何扩容后容量都会变成奇数

添加键值对

publicsynchronizedVput(Kkey,Vvalue){

//Makesurethevalueisnotnull

//Makessurethekeyisnotalreadyinthehashtable.

Vold=e.value;

e.value=value;

returnold;

if(count>

=threshold){

//Rehashthetableifthethresholdisexceeded

rehash();

tab=table;

hash=hash(key);

index=(hash&

//Createsthenewentry.

e=tab[index];

tab[index]=newEntry<

(hash,key,value,e);

count++;

注意键和值都必须不能为NULL添加过程中如果发现给定的key已经存在,那么替换旧值并返回旧值,否则将新的键值对加入到HashTable,其中如果添加过程中发现实际键值对数目已经超过阈值,那么就进行扩容

删除键值对

publicsynchronizedVremove(Objectkey){

e=tab[index],prev=null;

prev=e,e=e.next){

if(prev!

=null){

prev.next=e.next;

tab[index]=e.next;

count--;

VoldValue=e.value;

e.value=null;

returnoldValue;

如果找到了给定key对应的键值对,那么就做删除操作,如果没有找到,那么就什么也不做。

实际的删除过程就是单链表的节点删除

清空操作

publicsynchronizedvoidclear(){

for(intindex=tab.length;

--index>

=0;

tab[index]=null;

count=0;

和HashMap的清空操作一样,只是将每个slot置为NULL,剩下的交给GC

比较两个HashTable是否相等

publicsynchronizedbooleanequals(Objecto){

if(o==this)

if(!

(oinstanceofMap))

Map<

t=(Map<

)o;

if(t.size()!

=size())

try{

Iterator<

Map.Entry<

i=entrySet().iterator();

while(i.hasNext()){

Map.Entry<

e=i.next();

Kkey=e.getKey();

Vvalue=e.getValue();

(t.get(key)==null&

t.containsKey(key)))

value.equals(t.get(key)))

}catch(ClassCastExceptionunused){

returnlse;

}catch(NullPointerExceptionunused){

首先比较大小是否相等,如果大小相等,那么就依次比较实体集合中每个实体的是否是一样的键值对,如果所有的键值对都一样,那么就返回true,否则返回false,注意由于HashTable中数据存储并不是有序的,所以实际比较的时候使用的是get()根据指定的key获取对应的value

获取HashTable的hashCode

publicsynchronizedinthashCode(){

/*

*Thiscodedetectstherecursioncausedbycomputingthehashcode

*ofaself-referentialhashtableandpreventsthestackoverflow

*thatwouldotherwiseresult.Thisallowscertain1.1-era

*appletswithself-referentialhashtablestowork.Thiscode

*abusestheloadFactorfieldtododouble-dutyasahashCode

*inprogressflag,soasnottoworsenthespaceperformance.

*Anegativeloadfactorindicatesthathashcodecomputationis

*inprogress.

*/

inth=0;

if(count==0||loadFactor<

returnh;

//Returnszero

loadFactor=-loadFactor;

//MarkhashCodecomputationinprogress

Entry[]tab=table;

entry:

tab)

while(entry!

h+=entry.hashCode();

entry=entry.next;

//MarkhashCodecomputationcomplete

实际计算HashTable的hashCode是根据每个实体的hashCode来计算的,所有实体的hashCode()之和就是HashTable的hashCode。

loadFractor扮演了一个标志位的角色,标志计算的开始和结束。

关于这里h+=entry.hashCode()中h是否会溢出的问题,上面再hash()函数中已经看到了每次求hash的时候都会与0x7fffffff,也就是说hash永远为正,不会溢出

序列化和反序列化

privatevoidwriteObject(java.io.ObjectOutputStreams)

throwsIOException{

K,V>

entryStack=null;

synchronized(this){

//Writeoutthelength,threshold,loadfactor

s.defaultWriteObject();

//Writeoutlength,countofelements

s.writeInt(table.length);

s.writeInt(count);

//Stackcopiesoftheentriesinthetable

for(intindex=0;

index<

table.length;

index++){

entry=table[index];

entryStack=

newEntry<

(0,entry.key,entry.value,entryStack);

//Writeoutthekey/valueobjectsfromthestackedentries

while(entryStack!

s.writeObject(entryStack.key);

s.writeObject(entryStack.value);

entryStack=entryStack.next;

privatevoidreadObject(java.io.ObjectInputStreams)

throwsIOException,ClassNotFoundException

{

//Readinthelength,threshold,andloadfactor

s.defaultReadObject();

//sethashSeed

UNSAFE.putIntVolatile(this,HASHSEED_OFFSET,

sun.misc.Hashing.randomHashSeed(this));

//Readtheoriginallengthofthearrayandnumberofelements

intoriglength=s.readInt();

intelements=s.readInt();

//Computenewsizewithabitofroom5%togrowbut

//nolargerthantheoriginalsize.Makethelength

//oddifit'

slargeenough,thishelpsdistributetheentries.

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2