• HashMap


    在JDK1.7中,由”数组+链表“组成,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。

    在JDK1.8中,有“数组+链表+红黑树”组成。

    • 当链表超过8且数组长度(数据总量)超过64才会转为红黑树
    • 将链表转换成红黑树前会判断,如果当前数组的长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树,以减少搜索时间。

    HashMap的特点:

    • hashmap存取是无序的
    • 键和值位置都可以是null,但是键位置只能是一个null
    • 键位置是唯一的,底层的数据结构是控制键的
    • jdk1.8前数据结构是:链表+数组jdk1.8之后是:数组+链表+红黑树
    • 阈值(边界值)>8并且数组长度大于64,才将链表转换成红黑树,变成红黑树的目的是提高搜索速度,高效查询

    解决hash冲突:开放定址法、再哈希法、链地址法(HashMap中常见的拉链法)、建立公共溢出区。

    开放定址法也称为再散列法,基本思想就是,如果p=H(key)出现冲突时,则以p为基础,再次hash,p1=H(p),如果p1再次出现冲突,则以p1为基础,以此类推,直到找到一个不冲突的哈希地址pi。因此开放定址法所需要的hash表的长度要大于等于所需要存放的元素,而且因为存在再次hash,所以只能在删除的节点上做标记,而不能真正删除节点。

    再哈希法(双重散列,多重散列),提供多个不同的hash函数,R1=H1(key1)发生冲突时,再计算R2=H2(key1),直到没有冲突为止。这样做虽然不易产生堆集,但增加了计算的时间。

    链地址法(拉链法),将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除主要在同义词链表中进行,链表法适用于经常进行插入和删除的情况。

    建立公共溢出区,将哈希表分为公共表和溢出表,当溢出发生时,将所有溢出数据统一放到溢出区

    哈希表底层算法计算hash值

    hashCode方法是Object中的方法,所有的类都可以对其进行使用,首先底层通过调用hashCode方法生成初始hash值h1,然后将h1无符号右移16位得到h2,之后将h1与h2进行按位异或(^)运算得到最终hash值h3,之后将h3与(length-1)进行按位与(&)运算得到hash表索引

    其他可以计算出hash值的算法有

    • 平方取中法
    • 取余数
    • 伪随机数法
  • 相关阅读:
    BZOJ 3085: 反质数加强版SAPGAP
    BZOJ 1053 [HAOI2007]反素数ant
    强化学习一:Introduction Of Reinforcement Learning
    BZOJ 2120: 数颜色
    2018暑假多校(杭电 + 牛客)
    算法笔记--可持久化线段树
    牛客练习赛22 简单瞎搞题
    BZOJ 1047: [HAOI2007]理想的正方形
    算法笔记--二项式反演
    BZOJ 1010: [HNOI2008]玩具装箱toy
  • 原文地址:https://www.cnblogs.com/KL2016/p/16517367.html
Copyright © 2020-2023  润新知