当前位置: 首页 > article >正文

java散列表

  1. 散列表:
    1. 也叫做哈希表,这种数据结构提供了键Key和值Value的映射关系
    2. 只要给出一个Key,就可以高效查找到他所匹配的Value
    3. 时间复杂度接近于O(1)
  2. 哈希函数
    1. 通过哈希函数把Key和数组下标进行转换
    2. 在java及大多数面向对象的语言中,每一个对象都有属于自己的hashcode,这个hashcode是区分不同对象的重要标识,无论对象自身类型是什么,他们的hashcode都是一个整型变量
    3. 按照数组长度进行取模运算:index = HashCode(Key) % Array.length
    4. 通过hash函数,可以把字符串或其他类型的Key,转化成数组的下标index:
      1. 如给出一个长度为8的数组,则当key = 001121时,index = HashCode(“001121”) % Array.length = 1420036703 % 8 = 7
      2. 当key=this时,index = HashCode(“this”)%Array.length = 3559070%8 = 6
  3. 读写操作
    1. 写操作put:
      1. 写操作就是在散列表中插入新的键值对
      2. 如调用hashMap.put(“002931”,“lpy”);意思是插入一组key为002931,value为lpy的键值对
        1. 通过哈希函数,把Key转化为数组下标5
        2. 如果数组下标5对应的位置没有元素,就把这个Entry填充到数组下标5的位置
        3. 但是由于数组的长度是有限的,当插入的Entry越来越多时,不同的Key通过哈希函数获得的下标有可能是相同的,例如002936这个Key对应的数组下标是2,002947这个key对应数组下标也是2,这种情况叫做哈希冲突
      3. 解决哈希冲突:一种是开放寻址法,一种是链表法
        1. 开放寻址法:
          1. 当一个Key通过哈希函数获得对应的数组下标已被占用时,那么就寻找下一个空挡位置
          2. 例如:Entry6通过哈希函数得到下标2,改下标在数组中已经有了其他元素,那么就向后移动1位,看看数组下标3的位置是否有空,如果下标3的也已经被占用,那么就再向后移动1位,看看数组下标4的位置是否有空,如果数组下标4的位置还没有被占用,就把Entry6存入数组下标4的位置
          3. 在java中,ThreadLocal所使用的就是开放寻址法
          4. 开放寻址法的缺点在于删除元素的时候不能真的删除,否则会引起查找错误,只能做一个特殊标记,直到有下个元素插入才能真正删除该元素
        2. 链表法:
          1. HashMap数组的每一个元素不仅是一个Entry对象,还是一个链表的头节点,每一个Entry对象通过next指针指向他的下一个Entry节点,当新来的Entry映射到与之冲突的数组位置时,只需要插入到对应的链表中即可
    2. 读操作get
      1. 读操作就是通过给定的Key在散列表中查找对应的value
      2. 例如调用hashMap.get(“002936”),意思是查找key为002936的Entry在散列表中所对应的值
      3. 通过哈希函数,把key转化为数组下标2
      4. 找到数组下标2所对应的元素,如果这个元素的key是002936,那么就找到了,如果这个key不是002936也没关系,由于数组的每个元素都与一个链表对应,可以顺着链表往下找,看看能否找到与Key相匹配的节点
  4. 扩容
    1. 当经过多次元素插入,散列表达到一定饱和度时,key映射位置发生冲突的概率会逐渐提高,这样一来,大量元素拥挤在相同的数组下标位置,形成很长的链表,对后续插入操作和查询操作的性能都有很大影响
    2. 这时,散列表就需要扩展他的长度,也就是进行扩容
    3. 影响扩容因素有两个
      1. capacity:即hashmap的当前长度
      2. LoadFactor:即hashMap的负载因子,默认值为0.75f
    4. 衡量HashMap需要进行扩容的条件为:HashMap.Size >= Capacity * LoadFactor
    5. 扩容的步骤
      1. 扩容,创建一个新的Entry空数组,长度是原数组的2倍
      2. 重新Hash,遍历原Entry数组,把所有的Entry重新Hash到新数组中,因为长度扩大以后,hash的规则也随之改变,所以需要重新Hash
    6. 当多个Entry被Hash到同一个数组下标位置时,为了提升插入和查找的效率,HashMap会把Entry的链表转化为红黑树

http://www.kler.cn/news/359352.html

相关文章:

  • 2.链表(代码随想录——python版本)
  • 代码复现(四):DBINet
  • MongoDB聚合管道(Aggregation Pipeline)
  • 计算机基础 -- 计算机补码的原理
  • 【LeetCode:910. 最小差值 II + 模拟 + 思维】
  • 问:JVM中GC类型有哪些?触发条件有哪些?区别是啥?
  • 基于Spring Boot的大创项目高效管理系统
  • 关于Vue脚手架
  • 大模型日报10月21日
  • 利用透视变换实现文档矫正功能
  • AUTOSAR_EXP_ARAComAPI的5章笔记(13)
  • iOS IPA上传到App Store Connect的三种方案详解
  • chat_gpt回答:python使用writearray写tiff速度太慢,有什么快速的方法吗
  • UML(Unified Modeling Language,统一建模语言)
  • 基于Neo4j的推理知识图谱展示:智能系统与图谱可视化
  • Go 1.19.4 命令调用、日志、包管理、反射-Day 17
  • Git的认识及基本操作
  • 基于IP的真实地址生成器
  • 2024-10-17 问AI: [AI面试题] 讨论 AI 的挑战和局限性
  • 深度学习:YOLO目标检测和YOLO-V1算法损失函数的计算