哈希表提供了快速的插入操作和查找操作,每一个元素是一个key-value对,其基于数组来实现。
一、Java中HashMap与Hashtable的区别:
HashMap可以接受null键值和值,而Hashtable则不能。
Hashtable是线程安全的,通过synchronized实现线程同步。而HashMap是非线程安全的,但是速度比Hashtable快。
这两个类有许多不同的地方,下面列出了一部分:
a) Hashtable 是 JDK 1 遗留下来的类,而 HashMap 是后来增加的。
b)Hashtable 是同步(synchronized)的,比较慢,但 HashMap 没有同步策略,所以会更快。
c)Hashtable 不允许有个空的 key,但是 HashMap 允许出现一个 null key。
public classEmployee {privateString key;privateString name;publicString getKey() {returnkey;
}public voidsetKey(String key) {this.key =key;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicEmployee(String key, String name) {this.key =key;this.name =name;
}
}
员工类
importjava.math.BigInteger;public classHashTable {privateEmployee[] arr;publicHashTable() {
arr= new Employee[1000];
}public HashTable(intMaxsize) {
arr= newEmployee[Maxsize];
}//public void Insert(Employee emplo) {//以整型作为索引//arr[emplo.getKey()] = emplo;//}
public void Insert(Employee emplo) {//以字符串作为索引
arr[hashTable(emplo.getKey())] =emplo;
}//public Employee Find(int key) {//return arr[key];//}
publicEmployee Find(String key) {returnarr[hashTable(key)];
}public int hashTable(String key) {//转换AscII码存储,但存在码值重复问题
BigInteger hashVal = new BigInteger("0");
BigInteger pow27= new BigInteger("1");//int hashVal = 0;
int i = key.length() - 1;//int pow27 = 1;//27^0//for (; i >= 0; i--) {//int letter = key.charAt(i) - 96;//hashVal += letter;//}//return hashVal;//}
for (; i >= 0; i--) {int letter = key.charAt(i) - 96;
BigInteger letterB= newBigInteger(String.valueOf(letter));
hashVal= hashVal.add(letterB.multiply(pow27));//hashVal += letter * pow27;//hashVal += letter * pow27;//这里会溢出//pow27*=27
pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
}//return hashVal % arr.length;
return hashVal.mod(newBigInteger(String.valueOf(arr.length))).intValue();
}
}
方法类
public classDemo {public static voidmain(String[] args) {
HashTable ht= newHashTable();/*ht.Insert(new Employee(1, "Ally"));
ht.Insert(new Employee(2, "Jion"));
ht.Insert(new Employee(3, "Micale"));
ht.Insert(new Employee(4, "Lily"));
System.out.println(ht.Find(2).getName());*/ht.Insert(new Employee("aka", "74"));
System.out.println(ht.Find("aka").getName());
}
}
演示类
链地址法
public classLinkList {private Node first;//火车头,保存头结点的一个指向
public LinkList() {//初始化
first = null;
}public Node deleteFirst() {//删除头结点
first = first.next;//头结点为头结点的下一个
returnfirst;
}public Node find(String key) {//按值查找,返回null或索引值
Node current = first;//从头结点开始
while (!key.equals(current.emplo.getKey())) {if (current.next == null) {//尾结点后继为null
return null;
}
current=current.next;
}return current;//找到返回
}public Node delete(String key) {//删除任意结点
Node current =first;
Node previous=first;while (!key.equals(current.emplo.getKey())) {//找到current返回true !true = false
if (current.next == null) {//没有找到
return null;
}
previous= current;//保存邻近的两个结点
current =current.next;
}if (current == first) {//第一个结点
first =first.next;
}else {//后面的结点
previous.next = current.next;//上一个结点的下一个变为当前结点的下一个,当前结点删除
}return current;//结点类,返回结点类型
}public void insert(Employee emplo) {//在头结点之后插入
Node node = new Node(emplo);//创建新的结点//这里深深体会一下精妙之处,first保存着一个指向
node.next = first;//图示第一步
first = node;//图示第二步
}
}
链表
public class Node {//包装车厢
/*** 链结点*/
public Employee emplo;//数据域
public Node next;//指针域,后指针
public Node(Employee emplo) {//构造函数
this.emplo =emplo;
}
}
结点
importjava.math.BigInteger;public classHashTable {private LinkList[] arr; //每个数值对应一个链表
publicHashTable() {
arr= new LinkList[100];
}public HashTable(intMaxsize) {
arr= newLinkList[Maxsize];
}public void Insert(Employee emplo) {//以字符串作为索引
String key =emplo.getKey();int hashVal =hashTable(key);if (arr[hashVal] == null) {
arr[hashVal]= newLinkList();
}
arr[hashVal].insert(emplo);
}publicEmployee Find(String key) {int hashVal =hashTable(key);returnarr[hashVal].find(key).emplo;
}publicEmployee Delete(String key) {int hashVal =hashTable(key);returnarr[hashVal].delete(key).emplo;
}public int hashTable(String key) {//转换AscII码存储,但存在码值重复问题
BigInteger hashVal = new BigInteger("0");
BigInteger pow27= new BigInteger("1");int i = key.length() - 1;for (; i >= 0; i--) {int letter = key.charAt(i) - 96;
BigInteger letterB= newBigInteger(String.valueOf(letter));
hashVal=hashVal.add(letterB.multiply(pow27));
pow27= pow27.multiply(new BigInteger(String.valueOf(27)));
}return hashVal.mod(newBigInteger(String.valueOf(arr.length))).intValue();
}
}
方法
public classDemo {public static voidmain(String[] args) {
HashTable ht= newHashTable();/*ht.Insert(new Employee(1, "Ally"));
ht.Insert(new Employee(2, "Jion"));
ht.Insert(new Employee(3, "Micale"));
ht.Insert(new Employee(4, "Lily"));
System.out.println(ht.Find(2).getName());*/ht.Insert(new Employee("a", "Jack")); //开放地址法
ht.Insert(new Employee("ct","Rose"));
ht.Insert(new Employee("b", "Upon"));
System.out.println(ht.Find("a").getName());//打印对象
System.out.println(ht.Find("ct").getName());
System.out.println(ht.Find("b").getName());
System.out.println(ht.hashTable("a"));
System.out.println(ht.hashTable("ct"));
}
}
测试
参考文献:
https://www.cnblogs.com/aeolian/p/8468632.html
https://www.cnblogs.com/williamjie/p/9099141.html
http://www.luyixian.cn/news_show_10979.aspx