数据结构里的散列表高速索引的机制
- 散列表有m个存储单元,H(key) = key%P,P选择小于m的最大素数
- 长度为n的线性表,存放无序数据,平均查找时间是n/2
- 引入hash函数(散列函数),关联数据和存储位置
- 存取数据前,先用hash函数计算hash值,hash函数是X*X%5
- HashMap来源于数据结构里的散列表
散列表里解决冲突的方法
- 两个不同的值,有可能hash值相同,就引发冲突
- 散列表有多种解决方法,HashMap里用到了“链地址法”
在HashMap里存储不带hashcode和equals的对象
- 定义一个Key类,不重写hashcode和equals方法
- 实际用到了Object类里的hashcode和equals
- k1和k2的id都是1,用k1放,用k2取不出来
- 实际上,期望用k2取出值
import java.util.HashMap;
class Key{
private Integer id;
public Key(Integer id){
this.id = id;
}
public Integer getId() {
return id;
}
}
public class Test {
public static void main(String[] args){
Key k1 = new Key(1);
Key k2 = new Key(1);
HashMap<Key,String> hm = new HashMap<Key,String>();
hm.put(k1, "Key with id is 1");
System.out.println(hm.get(k2));
}
}
输出结果:null
不重写hashcode的后果
- k1和k2的hashcode不同,因为Object类的hashcode是返回地址
- k1存入的和k2获取的地址不同,所以返回是null
重写hashcode但不重写equals的后果
- 能用hashcode找到对应存储索引位
- 但可能会有冲突,所以需要再调用equals判断是否相等
- Key类里没重写equals方法,所以调用Object类的,以地址值判断
class Key{
private Integer id;
public Key(Integer id){
this.id = id;
}
public Integer getId() {
return id;
}
public int hashCode(){
return id.hashCode();
}
}
重写hashcode和equals
class Key{
private Integer id;
public Key(Integer id){
this.id = id;
}
public Integer getId() {
return id;
}
public int hashCode(){
return id.hashCode();
}
public boolean equals(Object o){
if(o == null||!(o instanceof Key)){
return false;
}else{
return this.getId().equals(((Key) o).getId());
}
}
}