1、简单实现哈希表
public class HashBuck {
static class Node{
public int key;
public int val;
public Node next;
public Node(int key,int val){
this.key=key;
this.val=val;
}
}
public Node[] array;
public int usedSize;
public static final double DEFAULT_LOAD_FACTOR=0.75;//规定负载因子,添加数据时检查一下,防止冲突
public HashBuck(){
this.array=new Node[10];
}
//添加元素
public void put(int key,int val){
//1、找到key所对应在array中的位置
int index=key% array.length;
//2、遍历index位置的链表,看key是否重复,重复则替换,若key不在则插入链表中
//2.1重复的时候
Node cur=array[index];
while(cur!=null){
if(cur.key==key){
cur.val=val;//key重复,替换val
return;
}
cur=cur.next;
}
//2.2不重复的时候:头插法插入
Node node=new Node(key, val);
node.next=array[index];//绑定尾部
array[index]=node;//绑定头部
usedSize++;
//3、检查负载因子,超出负载因子的值,则需要扩大array的容量来减小负载因子的值,防止冲突
if(loadFactor()>=DEFAULT_LOAD_FACTOR){
resize();//扩容array的方法
}
}
//扩容array需要注意:此时由于array扩容变长 需要将原来没扩容之前的节点都拿出来,
// 然后重新哈希每个节点找在扩容后数组中的位置
private void resize(){
Node[]newArray=new Node[2*array.length];
for (int i = 0; i < array.length; i++) {//遍历原来的数组,将里面的节点全都拿出来
Node cur=array[i];//拿里面的节点
while(cur!=null){//有可能array里的每个位置里都不止一个节点,而是一个链表
int index=cur.key%newArray.length;//找到节点在扩容后数组中的位置
Node curNext=cur.next;
cur.next=newArray[index];//绑定后面
newArray[index]=cur;//绑定前面
cur=curNext;
}
}
array=newArray;//让扩容后的数组代替原来的数组
}
private double loadFactor(){//求当前的负载因子值
return 1.0*usedSize/array.length;//负载因子=当前数据长度/数组长度
}
//根据key获取val值
public int get(int key){
//1、找key的位置(大概找到key所在array数组的哪个下标里)
int index=key%array.length;
//2、遍历这个下标的链表具体找到key
Node cur=array[index];
while(cur!=null){
if(cur.key==key){
return cur.val;
}
cur=cur.next;
}
return -1;
}
public static void main(String[] args) {
HashBuck hashBuck=new HashBuck();
hashBuck.put(1,1);
hashBuck.put(2,2);
hashBuck.put(4,4);
hashBuck.put(6,6);
hashBuck.put(13,13);
hashBuck.put(12,12);
hashBuck.put(11,11);
hashBuck.put(8,8);
System.out.println(hashBuck.get(11));
}
}
2、改进实现哈希表
import java.util.Objects;
//改进哈希表(由于哈希表里面的值不一定是整数)
class Person{
public String ID;
public Person(String ID){
this.ID=ID;
}
@Override
public String toString() {
return "Person{" +
"ID='" + ID + '\'' +
'}';
}
//如果哈希表里存的树自定义对象时,在进行插入和查找时要重写equals()和hashCode()两个方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(ID, person.ID);
}
@Override
public int hashCode() {
return Objects.hash(ID);
}
}
public class HashBuck2 <K,V>{
static class Node<K,V>{
public K key;
public V val;
public Node<K,V> next;
public Node(K key,V val){
this.key=key;
this.val=val;
}
}
public Node<K,V>[] array=(Node<K,V>[])new Node[10];
public int usedSize;
public void put(K key,V val){
int hash=key.hashCode();//通过hashCode()来将一个字符串转换成对应值,
// 进而通过生成的值来找其在array数组中的位置
int index=hash%array.length;
Node<K,V> cur=array[index];
while(cur!=null){
if(cur.key.equals(key)){
cur.val=val;
return;//此时相同的值再次插入,替换完val值后return
}
cur=cur.next;
}
Node<K,V> node=new Node<>(key,val);
node.next=array[index];
array[index]=node;
this.usedSize++;
}
public V get(K key){
int hash=key.hashCode();
int index=hash%array.length;
Node<K,V> cur=array[index];
while(cur!=null){
if(cur.key.equals(key)){
return cur.val;
}
cur=cur.next;
}
return null;
}
public static void main(String[] args) {
Person person1=new Person("123");
Person person2=new Person("123");
HashBuck2<Person,String> hashBuck2=new HashBuck2<>();
hashBuck2.put(person1,"ly");
System.out.println(hashBuck2.get(person2));
}
public static void main1(String[] args) {
Person person1=new Person("123");
Person person2=new Person("123");
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
}
本文详细介绍了哈希表的简单实现,并探讨了如何通过优化解决哈希冲突,提高数据存储和查找效率。
1242

被折叠的 条评论
为什么被折叠?



