HashMap的hash()方法

基础知识回顾

哈希算法

因为Java的HashMap源码里面有个混淆函数hash(),我就想补一下哈希的定义。
哈希算法有以下三个特点

  • 安全,给定数据 M 容易算出哈希值 X ,而给定 X 不能算出 M ,或者说哈希算法应该是一个单向算法。
  • 两个不同的数据,要拥有不相同的哈希。
  • 长度固定,给定一种哈希算法,不管输入是多大的数据,输出长度都是固定的。

仔细想一下,如果哈希的长度是固定的,也就是取值范围是有限的,而输入数据的取值范围是无限的,所以总会找到两个不同的输入拥有相同的哈希。所以,哈希函数的安全性肯定是个相对概念。如果出现了两个不同输入有相同输出的情况,就叫碰撞,collision 。不同的哈希算法,哈希位数越多,也就基本意味着安全级别越高,或者说它的”抗碰撞性“就越好。

位的操作

  • 正数的反码=原码=补码
  • 负数的反码为符号位保持不变,其余各位取反
  • 负数的补码就是在补码的基础上+1
    在这里插入图片描述

逻辑运算符

  • >>>: 无符号右移

按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。
其他结构和>>相似。

  • ^ : 位异或

0^0=0, 1^0=1, 0^1=1, 1^1=0

  • | : 或运算

0|0=0, 0|1=1, 1|0=1, 1|1=1

  • & : 与运算

0&0=0, 0&1=0, 1&0=0, 1&1=1

  • ~ : 非运算

~1=0, ~0=1

B树 和 B+树

B+树主要底部的叶子节点,和相连的节点有链接指向的关系。回去还得翻一翻以前的Sqlserver的索引的知识。

HashMap的实现原理

源代码主要通过数组+链表实现的,数组就是常说的桶,只是桶里装的是“糖葫芦”式的链表,还是树结构的数据。

hash()方法

这个扰动函数就是解决哈希出现相同key值的hash输入的可能性。

  • 获取key自带的hashCode
  • h再进行无符号向右移动16位,也就是取h的高16位
  • 这样的话自己的高半区和低半区做异或,就是为了混合原始哈希码的高位和低位,以此来加大低位的随机性。
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章