java哪个类开放地址法_开放地址法实现HashTable

前注:本文不是讲解Java类库的Hashtable实现原理,而是根据计算机哈希表原理自己实现的一个Hashtable。

HashTable内部是用数组存放一个(Key-Value pair)键值对的引用,其原理是根据Key的hashCode来计算出数组下标。因为存放位置是直接计算出来,不需要遍历数据结构,这使得hash table具有快速增删查改的优势。下面介绍HashTable的实现步骤:

取得Key的hashCode。

通过Eclipse等工具可以轻松的复写Object的hashCode方法,生成的hashCode是不会有重复值的。

将hashCode与地址映射(压缩地址):

但是,Hashtable内部是用一个数组来存储Key-Value对的,数组容量有限,本文中设置数组容量为10。那么现在的问题就是如何将hashCode和数组地址相对应?一个简单的方法就是对hashCode取模运算(hashCode%10)。这样就可以将hashCode与数组地址做映射(多对一)。同时注意,hashCode可能为负数,而数组的下标不能为负数,所以在映射的时候需要处理一下。

1 int hashCode = Math.abs(key.hashCode())% this.maxSize;

解决hashCode重复问题:

上文已经说过,数组容量为10,当我们在将hashCode映射为数组下标的时候,肯定会遇到有重复的情况。比如hashCode为21和31,分别对他们取模运算,结果都是1,也就是说这两个hashCode对应数组的下标都是1.那么第一个元素添加上去后,再添加第二个元素,则新元素会覆盖之前的元素。这时,如果我们想后面添加的重复地址元素也能添加上去,只能将其放在其它位置。这时,我们可以将新元素放在改地址的下一位,如果下一位已经有元素,那么就继续往后找,直到找到空位为止(其实这个过程有些边界条件需要考虑,比如找到数组末尾后应跳到数组开头继续找。以及数组已经满了,找遍数组都找不到合适的位置,就应该提示该数组已满,不能插入)。

现在既然解决了上面的问题,也就是说每个元素都能在数组中找到合适的位置(除非数组已满)。那么可以根据这个算法实现数组的增删查改。下面是Hashtable的实现代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageorg.lyk.impl;2

3 public class HashTable

4 {5 /**

6 * Key-Value pair 存放键值对7 *@authorliuyuank8 *9 */

10 private classKeyValue11 {12 K key;13 V value;14

15 privateKeyValue(K key, V value)16 {17 this.key =key;18 this.value =value;19 }20

21 publicK getKey()22 {23 returnkey;24 }25

26 public voidsetKey(K key)27 {28 this.key =key;29 }30

31 publicV getValue()32 {33 returnvalue;34 }35

36 public voidsetValue(V value)37 {38 this.value =value;39 }40

41 }42

43 privateObject[] table;44 private int maxSize = 10;45 private int currentAmmount = 0;46

47 publicHashTable()48 {49 this.table = new Object[this.maxSize];50 }51

52 public HashTable(int maxSize) throwsException53 {54 if (0 == maxSize || maxSize < 0 || maxSize > 100)55 {56 throw new Exception("table容量非法!");57 }58

59 this.maxSize =maxSize;60 this.table = newInfo[maxSize];61 }62

63 /**

64 * 增加一个键值对65 *@paramkey66 *@paramvalue67 */

68 public voidadd(K key, V value)69 {70 //将hashCode映射到数组下标

71 int hashCode = Math.abs(key.hashCode())% this.maxSize;72

73 //将元素插入到数组中,如果该位置已经被占用,则循环查找下一个位置,直到找到合适的位置,或发现数组已满,退出循环

74 while (this.table[hashCode] != null

75 && (this.currentAmmount < this.maxSize))76 {77 hashCode++;78 hashCode = hashCode % this.maxSize;79 }80

81 if (this.currentAmmount == this.maxSize)82 {83 //数组已满

84 System.out.println("Hash table 已满");85 } else

86 {87 //找到合适位置

88 this.table[hashCode] = newKeyValue(key, value);89 this.currentAmmount++;90 }91 }92

93 /**

94 * 与add方法同样的算法,根据key值找到数组中元素,然后将改元素设置为null95 *@paramkey96 *@return

97 */

98 public booleanremove(K key)99 {100 int hashCode = Math.abs(key.hashCode()) % this.maxSize;101 int count = 0;102 while (this.table[hashCode] != null && count < this.maxSize)103 {104 if (((KeyValue) this.table[hashCode]).getKey().equals(key))105 {106 this.table[hashCode] = null;107 return true;108 }109 count++;110 hashCode++;111 hashCode = hashCode%this.maxSize;112 }113

114 return false;115 }116

117 publicV get(K key)118 {119 int hashCode = Math.abs(key.hashCode()) % this.maxSize;120 int count = 0;121 while (this.table[hashCode] != null && count < this.maxSize)122 {123 if (key.equals(((KeyValue)this.table[hashCode]).getKey()))124 return ((KeyValue) this.table[hashCode]).getValue();125

126 hashCode++;127 count++;128 hashCode = hashCode%this.maxSize;129 }130 return null;131 }132

133 public booleancontains(K key)134 {135 if (this.get(key) != null)136 {137 return true;138 } else

139 {140 return false;141 }142 }143

144 public voidreplace(K key, V value)145 {146 KeyValue kv = this.find(key);147 if(kv != null)148 {149 kv.setValue(value);150 }151 }152

153 privateKeyValue find(K key)154 {155 int hashCode = Math.abs(key.hashCode()) % this.maxSize;156 int count = 0;157 while (this.table[hashCode] != null && count < this.maxSize)158 {159 if (key.equals(((KeyValue)this.table[hashCode]).getKey()))160 return ((KeyValue) this.table[hashCode]);161

162 hashCode++;163 count++;164 hashCode = hashCode%this.maxSize;165 }166 return null;167 }168 }

HashTable实现

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageorg.lyk.impl;importjava.math.BigInteger;public classInfo

{privateString name;privateString address;privateInteger age;publicInfo(String name, String address, Integer age)

{super();this.name =name;this.address =address;this.age =age;

}

@Overridepublic inthashCode()

{final int prime = 31;int result = 1;

result= prime * result + ((address == null) ? 0: address.hashCode());

result= prime * result + ((age == null) ? 0: age.hashCode());

result= prime * result + ((name == null) ? 0: name.hashCode());returnresult;

}//@Override//public int hashCode()//{//final int prime = 27;//int result = 1;//result = prime*result + (this.name == null ? 0:this.name.hashCode());//result = prime*result + (this.address == null ? 0:this.address.hashCode());//result = prime*result + (this.age == null ? 0 : this.age.hashCode());//return result;//}

@Overridepublic booleanequals(Object obj)

{if (this ==obj)return true;if (obj == null)return false;if (getClass() !=obj.getClass())return false;

Info other=(Info) obj;if (address == null)

{if (other.address != null)return false;

}else if (!address.equals(other.address))return false;if (age == null)

{if (other.age != null)return false;

}else if (!age.equals(other.age))return false;if (name == null)

{if (other.name != null)return false;

}else if (!name.equals(other.name))return false;return true;

}publicString getName()

{returnname;

}public voidsetName(String name)

{this.name =name;

}publicString getAddress()

{returnaddress;

}public voidsetAddress(String address)

{this.address =address;

}publicInteger getAge()

{returnage;

}public voidsetAge(Integer age)

{this.age =age;

}

@OverridepublicString toString()

{return "Info [name=" + name + ", address=" + address + ", age=" +age+ "]";

}

}

Value实现

测试代码:String为Key Info为Value

packageorg.lyk.main;importorg.lyk.impl.BiTree;importorg.lyk.impl.HashTable;importorg.lyk.impl.Info;public classMain

{public static voidmain(String[] args)

{

HashTable ht = new HashTable<>();for(int i =0; i <15;i++)

{

Info info= new Info("sheldon" + i, "address" +i , i);//System.out.println("hashCode in main:" + info.getName().hashCode());

ht.add(info.getName(), info);

}

String key= "sheldon3";

System.out.println(ht.contains(key));

ht.replace(key,new Info("谢耳朵","美国洛杉矶", 999));

System.out.println(ht.contains(key));

System.out.println(ht.get(key));

System.out.println("///~ main done");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值