一.什么是哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通 过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组 叫做散列表.
二.实现一个需求
有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址..),当输入该员工的 id 时, 要求查找到该员工的 所有信息。
- 不使用数据库,速度越快越好。
- 添加时,保证按照 id 从低到高插入。-----》使用id/size作为hash值。
- 使用链表来实现哈希表, 该链表不带表头。
- 原理图:
代码:
public class HashDemo {
public static void main(String[] args) {
//创建哈希表
HashTable hashTab = new HashTable(7);
//写一个简单的菜单
String key = "";
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("add: 添加雇员");
System.out.println("list: 显示雇员");
System.out.println("find: 查找雇员");
System.out.println("exit: 退出系统");
key = scanner.next();
switch (key) {
case "add":
System.out.println("输入id");
int id = scanner.nextInt();
System.out.println("输入名字");
String name = scanner.next();
//创建 雇员
Emplyee emp = new Emplyee(id, name);
hashTab.addEmp(emp);
break;
case "list":
hashTab.list();
break;
case "find":
System.out.println("请输入要查找的id");
id = scanner.nextInt();
hashTab.findEmpById(id);
break;
case "exit":
scanner.close();
System.exit(0);
default:
break;
}
}
}
}
//hashtable
class HashTable {
private EmpLinkedList[] empLinkedLists;// 存放链表的集合
private int size;// 数组大小
public HashTable(int size) {
this.empLinkedLists = new EmpLinkedList[size];
this.size = size;
//初始化每一条链表
for (int i = 0; i < empLinkedLists.length; i++) {
empLinkedLists[i] = new EmpLinkedList();
}
}
// 添加emp
public void addEmp(Emplyee emp) {
int hash = calculateHashValue(emp.getId());
empLinkedLists[hash].addEmp(emp);
}
//遍历list
public void list() {
for (int i = 0; i < empLinkedLists.length; i++) {
empLinkedLists[i].list(i);
}
}
//找到id对应的结点
public void findEmpById(int no) {
int hash = calculateHashValue(no);
empLinkedLists[hash].findEmpById(no);
}
// 哈希值h
public int calculateHashValue(int id) {
return id % size;
}
}
//构造链表
class EmpLinkedList {
// 头结点
Emplyee head = null;
// 添加结点
public void addEmp(Emplyee emp) {
// 头节点为空,直接添加
if (head == null) {
head = emp;
return;
}
Emplyee temp = head;
while (true) {
if (temp.next == null) {// 说明到了链表尾部
break;
}
temp = temp.next;
}
temp.next = emp;
}
// 遍历链表
public void list(int no) {
if (head == null) {// 空链表
System.out.println("第"+(no+1)+"空链表");
return;
}
Emplyee temp = head;
System.out.print("第"+(no+1)+"链表的信息为");
while (true) {
System.out.printf("==>id=%d,name=%s\t", temp.getId(), temp.getName());
System.out.println();
if (temp.next == null) {// 链表尾结束
break;
}
temp = temp.next;
}
}
// 根据id遍历
public void findEmpById(int no) {
if (head == null) {
return;
}
Emplyee temp = head;
while (true) {
if (temp.getId() == no) {
System.out.printf("==>id=%d,name=%s\t", temp.getId(), temp.getName());
break;
}
if (temp.next == null) {
break;
}
temp = temp.next;
}
}
}
//链表结点---雇员
class Emplyee {
private int id;
private String name;
Emplyee next;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Emplyee getNext() {
return next;
}
public Emplyee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public void setNext(Emplyee next) {
this.next = next;
}
}
总结:每条链表在构造时要进行初始化。