哈希表原理初解(hashtable)

哈希表结构特点

ctrl+alt+左右箭头返回鼠标上次下次焦点

  • hashtable也叫散列表
  • 特点:快
  • 结构:结构有多种(最常用、最容易理解的结构( JDK1.7 ) :数组+链表
    JDK1.8:数组+链表/红黑树(链表长度>=8 ))
  • 最流行、最容易理解:顺序表+链表
  • 主结构:顺序表
    每个顺序表的节点在单独引出一个链表
    在这里插入图片描述

添加与查找数据

  1. 计算哈希码(调用hashCode(),结果是一个int值 ,整数的哈希码取自身即可)
  2. 计算在哈希表中的存储位置y=k(x)=x%11
    x:哈希码
    k(x) :哈希函数
    y :在哈希表中的存储位置,y值一样就会出现hash冲突(无法避免)。
  3. 存入哈希表
    情况1 : 一次添加成功
    情况2 :多次添加成功(出现了冲突,调用equals()和对应链表的元素进行比较,比较到最后,结果都是false ,创建新节点,存储数据,并加入链表末尾)
    情况3 :不添加(出现了冲突,调用equals(和对应链表的元素进行比较,经过一次或者多次比较后,结果是true ,表明重复,不添加)

结论1 :哈希表添加数据快( 3步即可,不考虑冲突)
结论2 :唯一
结论3:无序
查找也是直接生成哈希码,计算地址,链表查找。

hashCode()和equals()的作用

hashCode():计算哈希码是一个整数.根据哈希码可以计算出数据在哈希表中的存储位置
equals() :添加时出现了冲突。需要通过equals进行比较,判断是否相同
查询时也需要使用equals进行比较,判断是否相同

各基础数据类型hash码

String的hashCode

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

自定义类重写hashCode方法,会对基本数据类型的hash码通过计算生成类的hash码。

@Override
public int hashCode() {
    int result;
    long temp;
    result = sno;
    result = 31 * result + name.hashCode();
    result = 31 * result + age;
    temp = Double.doubleToLongBits(score);
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    return result;
}

减少哈希冲突

  1. 表中的记录数/哈希表的长度=装填因子:
    如果Hash表的空间远远大于最后实际存储的记录个数,则造成了很大的空间浪费如果选取小了的话,则容易造成冲突。
    在实际情况中, 一般需要根据最终记录存储个数和关键字的分布特点来确定Hash表的大小。
    还有一种情况,可能事先不知道最终需要存储的记录个数,则需要动态维护Hash表的容量,此时可能需要重新计算Hash地址。
    装填因子=表中的记录数/哈希表的长度
    12/16 =0.75
    如果装填因子越小,表明表中还有很多的空单元,则添加发生冲突的可能性越小;而装填因子越大.则发生冲突的可能性就越大.在查找时所耗费的时间就越多。
    有相关文献证明当装填因子在0.5左右的时候。Hash的性能能够达到最优。因此,一般情况下.装填因子取经验值0.5。
  2. 哈希函数的选择
    重接定址法、平方取中法折叠法、除留取余法(y= x%11)
  3. 处理冲突的方法
    链地址法(冲突值以链表方式存储)、开放地址法再散列法、建立一个公共溢出区

Java中HashSet, LinkedHashSet, HashMap. LinkedHashMap. Hashtable底层使用的都是哈希表
JDK1.8之后,哈希表的底层结构发生了变化.如果链表的长度>=8.就会将造表转换为红黑树。目的是为了减少查询比较的次数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值