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

一、数据结构

在这里插入图片描述

顺序存储:

  1. 性质:连续的存储单元来存储数据(逻辑上连续,物理上也连续)
  2. 特点:随机存取。适合查找,不适合增删;更节约空间

链式存储:

  1. 性质:非连续的存储单元来存储数据(逻辑上连续,物理上不一定连续)
  2. 特点:非随机存取。适合增删,不合适查找;有指针域,空间利用率比顺序存储低

索引存储:

  1. 性质:通过增加索引(相当于书的目录),来检索目标,一般使用B+树实现
  2. 特点:检索快,插入慢。费空间
  3. 延伸:B+树和B-树的最主要区别之一是B+树只有叶子节点才存储data信息,而B-树在其他节点也存储信息
  4. 注意:B树就是B-树,B-tree(balance-tree,平衡树)

哈希/散列存储:

  1. 性质:通过哈希函数计算出key的哈希值并找到存储位置,然后定位目标。存储位置index = f(key)
  2. 特点:检索快。可能有哈希冲突要解决
  3. 构建哈希函数:直接寻址,除数取余等
  4. 解决哈希冲突:开放寻址(a、线性探查;b、平方探查),链地址/拉链法(hashmap采用此法,数组+链表)等
  5. 注意:哈希表的主干是数组,利用其可以随机存取特性;如用链地址法,则还有链表分支

注意:数据的逻辑结构可以用多种不同的存储结构表示

二、HashMap

在这里插入图片描述

HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好

产生链表的原因:不同的key经过hash函数得到相同的hash值。所以需要保证,相同key对象,hash值一定相等,但是不同的key对象,可能有相同的hash值

重要知识点

  1. 负载因子:默认是0.75,一般在0.6-0.9之间比较好,可以减少哈希冲突。如 已存元素/内存空间 >= 负载因子,则空间会扩容一倍

  2. 存储下标:生成过程如下图在这里插入图片描述

  3. 为什么HashMap数组长度是2的幂次方?a,扩容只是左边增加一位,保证新老数组一致性;b,可以保证index分布均匀;c,可以最大化利用数组

  4. 为什么重写equals()要重写hashcode()方法?因为在生成存储下标的时候调用了hashcode()方法,默认的hashcode()方法继承自Object类的native hashcode()方法,而此方法是java调用的C++底层实现,用于获取对象的存储地址。如果只重写equals()方法,那么会出现对象内容一致但是存储位置不一致的情况而导致无法精确匹配。重写hashcode()方法在于人为控制内容一致的对象有相同的hashcode码。

Object的hashCode()方法
在这里插入图片描述

HashMap的put()方法

public V put(K key, V value) {  
        //如果table数组为空数组{},进行数组填充(为table分配实际内存空间),入参为threshold,
        //此时threshold为initialCapacity 默认是1<<4(左位移4,2的4次方=16)
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
       //如果key为null,存储位置为table[0]或table[0]的冲突链上
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);//对key的hashcode进一步计算,确保散列均匀
        int i = indexFor(hash, table.length);//获取在table中的实际位置
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        //如果该对应数据已存在,执行覆盖操作。用新value替换旧value,并返回旧value
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            // 先判断hash值是否一致,如果一致,再判断key值是否相等。如果hash值一致,则不需要再进行key值的equals的判断,可以提高效率。
            // 如果重写了equals()方法,则需要重写hashcode()方法。因为key生成hash码时,先调用了hashcode()方法。默认的hashcode()方法继承自Object的native hashcode()方法,而此方法是java调用的C++底层实现,用于获取对象的存储地址。如果只重写equals()方法,那么会出现key对象内容一致但是存储位置不一致的情况而无法精确匹配。重写hashcode()方法以保证相同内容的key对象有相同的hashcode值
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;//保证并发访问时,若HashMap内部结构发生变化,快速响应失败
        addEntry(hash, key, value, i);//新增一个entry
        return null;}

HashMap的hash()方法
对key对象的hashcode进一步进行计算以及二进制位的调整等来保证最终获取的存储位置尽量分布均匀

final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }
        h ^= k.hashCode();
        // 调用了hashCode()函数,重写此函数以保证相同的key对象有相同的hashCode值
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

参考:https://blog.csdn.net/woshimaxiao1/article/details/83661464

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-14 02:14:08  更:2022-01-14 02:14:30 
 
开发: 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年11日历 -2024/11/26 18:50:17-

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