IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> HashMap究极详细 -> 正文阅读

[数据结构与算法]HashMap究极详细

HashMap底层详解

1.简介

? HashMap是java种使用频繁的数据结构,其储存对象是无序的,以key,value的形式存放

? 1.key可以为null

? 2.key不能重复,如果key重复则会覆盖第一个key的value

? 3.一个key,对应一个value

2.HashMap的常用方法

方法解释
put(key,value)存入一对键值对key,value,如果key已存在则用这个value覆盖掉以前的,不存在则加入
get(key)通过key来获取值
values()获得所有的value
keySet()获得所有的key
isEmpty()判断是否为空
putAll(map)把另一个map全部加入这个map
containsKey(key)判断map种是否包含这个key
containsValue(value)判断map中是否包含这个value
size()map的长度

3.底层数据结构

? hashMap底层的数据结构是以数组和链表的形式。

? 数组:查找快

? 链表:增删快

? 这也是设计成数组+链表的原因

? 底层的数组默认长度为16,随着map长度的加大可能会扩容,当链表变长的时候链表的数据结构也会变

以及为什莫数组默认长度为16?(下面会一 一陈述)

? 查看源图像

HashMap储存对象时:***key所属的类***必须重写Object类里的HashCode()和equals()

HashCode():会为每个对象产生一个Hash值。 保证了高效性

equals():根据hash值判断两个对象是否一样,Hash值不一样两个***一定不相等***有

时可能会有两个对象Hash值相等但值不一样,这时候要调用equals()比对两个对

象是否真的一致(保证key不重复)。 保证了准确性

4.Hash冲突

? 1.存入对象时,先算出其的Hash值然后和数组的长度求余也就是(Hash%16)算出来的值就是其存在的数组位数。

? 2.如果这一位已经有对象了那么就往下面链表里坠,next直到下一个为空,则把这个对象放到这。

5.Hash容量以及扩容机制

1.负载因子

? HashMap中有一个默认负载因子为0.75

? 为什莫为默认负载因子0.75?

? ① 阈值=负载因子容量*容量为2的幂次方所以必须保证

? 容量*负载因子为整数

? ② 负载因子越大Hash冲突越多,负载因子越少,空间浪费越大,权衡得出结果

2.扩容机制

? 当元素数量大于阈值则需要扩容,将数组长度按位向左移一位

? 由于:计算机底层按位移操作快(乘法的底层为加法效率不高)

? HashMap的容量是有上限的,必须小于1<<30,即1073741824。如果容量超出了这个数,则不再增长,且阈值会被设置为 Integer.MAX_VALUE( [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7P6Ksaik-1626959298692)(https://www.zhihu.com/equation?tex=2%5E%7B31%7D-1)] ),即永远不会超出阈值了)。

3.HashMap的数组开始长度为什莫为16

首先我们看hashMap的源码可知当新put一个数据时会进行计算位于table数组(也称为桶)中的下标:

int index =key.hashCode()&(length-1);

hashmap每次扩容都是以 2的整数次幂进行扩容

比如: 十进制: 201314

二进制: 11 0001 0010 0110 0010

假设初始化大小为16

15转化为二进制: 1111

index : 11 0001 0010 0110 0010 & 1111 =0010 为 3

? 因为是将二进制进行按位于,(16-1) 是 1111,末位是1,这样也能保证计算后的index既可以是奇数也可以是偶数,并且只要传进来的key足够分散,均匀那么按位于的时候获得的index就会减少重复,这样也就减少了hash的碰撞以及hashMap的查询效率。

? 这样看起来2的n次方都可以,但8和4太小,Hash碰撞太多,32太大故选16

6.HashMap中的扰动函数

什么为扰动函数?

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

对象在Hash表中存放的位置算法为=key.hashCode()&(length-1);

又由于Hash表初始长度为16,减去1为15

00000000 00000000 00000000 00001111与无论什么值取&结果都只能由后四位决定(0&1=0; 0&0=0; 1&0=0; 1&1=1;)

例如

? 00000000 00000000 00000000 00001111 16-1 (16hash表初始长度)

? 11000101 10011101 10000001 11110100 HashCode

? 00000000 00000000 00000000 00000100 结果

? 这样做的话hash冲突会很大所以采用一个办法,将hashCode右移16位与自己取^,产生的值作为新值去做运算

? 00000000 00000000 11000101 10011101 HashCode

? 11000101 10010101 10000001 11110100 h>>>16

? 11000101 10010101 01000100 01101001 新值 (更加散列)

用新值算对象在Hash表中存放的位置算法为=key.hashCode()&(length-1);

又由于Hash表初始长度为16,减去1为15

? 00000000 00000000 00000000 00001111

? 11000101 10010101 01000100 01101001

? 00000000 00000000 00000000 00001001

? 等于9

获得的值更加散列,减少Hash冲突

7.HashMap底层在·jdk1.8后的改动

? 当发现链表表中的链表长度大于8时,当发现链表中的元素个数大于8之后,

1.还会判断一下当前数组的长度,如果数组长度小于64时,此时并不会转化为红黑树,而是进行扩容。

2.只有当链表中的元素个数大于8,并且数组的长度大于等于64时才会将链表转为红黑树
在这里插入图片描述

?

?

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 00:10:44  更:2021-07-24 00:11:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 6:10:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码