美文网首页
Java数据结构_哈希表_基本概念

Java数据结构_哈希表_基本概念

作者: 信仰年輕 | 来源:发表于2021-04-20 14:47 被阅读0次

本文目标

哈希表的基本概念,哈希冲突,哈希函数

什么是哈希表

哈希表也叫做散列表(hash有剁碎的意思)
哈希表是空间换时间的典型应用
哈希表内部的数组元素,很多地方也叫做Bucket(桶),整个数组叫Buckets或者 Bucket Array

哈希冲突

哈希冲突也叫做哈希碰撞
2个不同的key,经过哈希函数计算得到相同的结果

JDK1.8的哈希冲突解决方案

默认采用采用单向链表将元素穿起来
在添加元素的时候也可以能由单向链表转成红黑树,比如当哈希表容量≥64 且单向链表的节点数量>8
当红黑树节点数量少到一定程度时候,又会转为单向链表

为什么使用单链表?

1.每次都是从头结点开始遍历
2.单向链表比双向链表少一个指针,节省内存空间

哈希函数

哈希表中哈希函数的实现步骤大概如下
1.先生成key的哈希值(必须是整数)
2.在让key的哈希值和数组的大小进行相关运算,生成一个索引值

public int  hash(Object key) {
    return hashCode(key) % table.length;
}

为了提高效率,可以使用&位运算取代%运算【前提:将数组的长度设计为2的幂(2^n)】

public int  hash(Object key) {
    return hashCode(key) & (table.length-1);
}

为什么可以使用&位运算取代%运算
二进制 2^n

10                 2^1
100                2^2
1000               2^3
10000              2^4

二进制 2^n - 1

01                 2^1-1
011                2^2-1
0111               2^3-1
01111              2^4-1

不难发现,都是2^n - 1 转成二进制都是一排1(最前面的0可以忽略)

假如说现在hash_code(key)为10101,然后与数组长度为(2^3 - 1)做&运算

  10101    哈希值
& 00111    数组的长度
---------------
  00101    索引值

得出来的结果 00101必然是小于00111的(数组的长度2^3 - 1)

良好的哈希函数
让哈希值更加均匀分布->减少哈希冲突此时->提升哈希表的性能

如何生成key的哈希值

key的常见种类可能有
1.整数,浮点数,字符串,自定义对象
2.不同种类的key,哈希值的生成方式不一样,但目标是一致的
尽量让每个key的哈希值是唯一的
进来让key的所有信息参与运算

1.整数的哈希值

把整数值当做哈希值
比如10的哈希值就是10

public static int  hashCode(int value) {
    return value;
}

2.浮点数的哈希值

将存储的二进制个数转为整数值

public static int  hashCode(float value) {
    return Float.floatToIntBits(value);
}

3.Long的哈希值

public static int  hashCode(long value) {
    return (int)(value ^ (value >>> 32));
}

4.Doble的哈希值

public static int  hashCode(double value) {
      //long类型的64位的二进制数据
     long bits = Double.doubleToLongBits(value);
     //进行低32位和高32位的 异或运算(相同为0,不同为1),算出哈希值
     return (int)(bits ^ (bits >>> 32));
}

>>> 和 ^ 的作用是?

1.高32bit和低32bit混合计算出32bit的哈希值
2.充分利用所有信息计算出哈希值


上图,value 和 value>>>32 (右移32位) 做异或^运算
此时,是value的低32位和高32位做异或^运算

|或运算,有一个为1就为1
所以不能用或运算,只能用异或
异或运算,相同为0,不同为1

5.字符串的哈希值

整数5489是如何计算出来的?

5 * 10^3 + 4 * 10^2 + 8 * 10^1 + 9 * 10^0

字符串是由若干个字符组成的
1.比如字符串jack,由j,a,c,k四个字符组成(字符的本质就是一个整数)
2.因此,jack的哈希值可以表示为

j * n^3 + a * n^2 + c * n^1 + k * n^0

等价于

[(j * n + a) * n + c] * n + k

3.在JDK中,乘数n为31,为什么使用31?
31是一个奇素数,JVM会将31 * i 优化成 (i<<5) -1

public static int  hashCode(String value) {
        int hashCode = 0;
        int len = value.length();
        for(int i=0;i<len;i++) {
            char c = value.charAt(i);
            hashCode = 31 * hashCode +c;
        }
        return  hashCode;
}

相关文章

  • 哈希表—什么是哈希表

    冰冻非一日之寒 哈希表是一种数据结构~ 基本概念 哈希表可以存储各种类型的数据,当我们从哈希表中查找所需要的数据时...

  • 数据结构:Hash Table

    一、基本概念哈希表(hash table)是一种根据关键字直接访问内存存储位置的数据结构,通过哈希表,数据元素的存...

  • Java核心类库—— 数据结构

    Java核心类库-------数据结构体系图 1.数据结构 2.栈 3.哈希表

  • Java数据结构_哈希表_基本概念

    本文目标 哈希表的基本概念,哈希冲突,哈希函数 什么是哈希表 哈希表也叫做散列表(hash有剁碎的意思)哈希表是空...

  • 数据结构_哈希表(Java)

    在讲解HashMap集合之前,我们先说说一个重要的数据结构---哈希表。哈希表是一种非常优秀数据结构,对哈希表进行...

  • 哈希表 - HashTable

    基本概念 哈希表是一种特殊的数据结构,通过索引,能快速的查找到某个元素。 设计原理 通过哈希函数,将key映射到v...

  • 【三】哈希表

    前言 哈希表基本上是我见过使用最广泛的数据结构了,不管是PHP,MySQL,Redis,JAVA等,都使用到了哈希...

  • 「Redis源码解读」—数据结构(二)哈希表

    Redis的字典使用哈希表作为底层实现 知识点 1.数据结构 哈希节点 哈希表 类型处理函数 2.哈希 哈希算法 ...

  • Java集合框架

    Java 集合工具包位于 Java.util 包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表...

  • HashMap和HashTable源代码分析

    哈希表是一种能够进行快速查找且能够支持高效插入的数据结构,JAVA已经有多个不同的类实现了哈希表,在日常应用中,我...

网友评论

      本文标题:Java数据结构_哈希表_基本概念

      本文链接:https://www.haomeiwen.com/subject/oocnlltx.html