闲碎记事本 闲碎记事本
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

YAN

我要偷偷记录...
首页
  • JAVA
  • Cloudflare
  • 学完再改一遍UI
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • java

    • SpringBoot

    • SpringSecurity

    • MybatisPlus

    • Netty

    • sip

    • 其他

      • MDC 使用
      • 位运算
      • RedisMQ实现
      • 自定义枚举序列化
      • Mybatis使用自定义枚举
      • Jackson反序列化泛型注意点
      • 敏感词过滤算法
      • 线程
      • 并发学习
      • jni使用
      • 关于注释
      • 为什么一个Byte用两个16进制表示
      • JAVA获取系统信息
      • 对extends和super的理解
      • JAVA系统API
      • java探针初探
      • JAVA获取USB信息
      • HashMap初探
        • 1.7
        • 1.8
          • Hash冲突解决
          • 链地址法:
      • JAVA远程调试
      • 初探webflux
      • SSE示例
  • linux

  • docker

  • redis

  • nginx

  • mysql

  • 其他

  • 环境搭建

  • 知识库
  • java
  • 其他
YAN
2023-09-19
目录

HashMap初探

# 1.7

数组+ 链表 头插法

初始化大小 数组的大小,必须是 2 << 30,初始化会根据传入大小匹配最近的值 例如:

new HashMa(3); -> length = 4
new HashMa(5); -> length = 8
new HashMa(10); -> length = 16
new HashMa(17); -> length = 32

计算下标 得到key的hash Code 和数组长度进行逻辑与& 操作

示例: Key的 Hash Coed = 0011 1101

#初始化大小为10 匹配的值为16 ,将(size -1)得到 15
对应hash code   =  00000 1111
#进行 &amp; 运算    
0011 1101
0000 1111    
得到
0000 1101  -> 得到对应的下标:13

#初始化大小为17 匹配的值为32 ,将(size -1)得到 31
对应hash code   =  0011 1111
#进行 &amp; 运算    
0011 1101
0001 1111    
得到
0001 1101  -> 得到对应的下标:29 ==(13+16)

Key的 Hash Coed = 0010 1101

#初始化大小为10 匹配的值为16 ,将(size -1)得到 15
对应hash code   =  00000 1111
#进行 &amp; 运算    
0010 1101
0000 1111    
得到
0000 1101  -> 得到对应的下标:13

#初始化大小为17 匹配的值为32 ,将(size -1)得到 31
对应hash code   =  0011 1111
#进行 &amp; 运算    
0010 1101
0001 1111    
得到
0000 1101  -> 得到对应的下标:13  

由上面两图得到结果:

Hash根据key的值进行散列计算,将key分别放置于数组中, 由于hash code 会存在相同情况,此时会发生hash碰撞,hashMap 中使用链地址法, 但不同的是,HashMap会将冲突的数据链接到链表头部(PS:避免遍历去找到最后一个数据) 然后将链表下移。

伪代码

class HashMap<K,V> {

    Node<K, V> nodes;
    
    int size;
    
    public V put(K k,V v){
         //创建节点
        if(null == nodes || nodes.length == 0){
            nodes = resize();
            size =nodes.length;
        } 
         //根据k得到hash编码后,取出对应的节点
        int index = getIndex(getHash(k));
        //根据下标得到老节点
        Node<K,V> oldVal =  nodes[index];
        //得到节点为null
        if( null == oldVal){
            //创建一个新节点
           nodes[index] = new  Node(k,v,null);
        }else{
            //创建一个新节点,并将老节点设置为子节点
		   nodes[index] = new  Node(k,v,oldVal);
        }
        size++;
        //此处省略链表内部数据替换的代码。。。
        return 新插入一个key返回null,重复插入相同的Key,返回被替换值;
    }
    
    //为什么效率好,直接返回效率能不高吗
    public int size() { return size}
}
class Node<K,V> {
//键
private K key;
//值
private K val;
//子节点
private Node<K,V> next;

    public Node(K k,V v){
       this.k = k;
       this.v = v;
    }
    public Node(K k,V v,Node<K,V> next){
	   this.k = k;
       this.v = v;
       this.next = next;
    }
}

# 1.8

数组+链表 + 红黑树

# Hash冲突解决

# 链地址法:

将所有hash编码相同的字符生成一个链表,发生冲突是链接到链表尾部

待续...

上次更新: 2025/05/22, 07:52:48
JAVA获取USB信息
JAVA远程调试

← JAVA获取USB信息 JAVA远程调试→

最近更新
01
Caddy操作指南
04-25
02
虚拟机磁盘扩展
04-22
03
Swap空间
04-22
更多文章>
Theme by Vdoing | Copyright © 2022-2025 YAN | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式