Java集合之一——HashMap(辨析)

这篇具有很好参考价值的文章主要介绍了Java集合之一——HashMap(辨析)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

看到一篇讲hashmap的文章,讲的很不错,但是有一点我觉得作者没有讲清楚,这里我说一下自己的理解。

原文,先看原文:

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

前文概述,该博客的主要内容如下:

1. 什么是哈希表(主干为数组)、什么是哈希冲突、如何解决哈希冲突。这些大都是数据结构的基础知识,这里不再赘述

2.hashmap的实现原理:

简要概述一下:

主干是数组,冲突用链表解决。

每个元素其实都一个entry对象。

默认容量为16,负载因子0.75,当前元素数量大于等于容量*负载因子,扩容。

扩容后的大小为最接近当前size的二次幂。

在扩容之后,会进行元素迁移,从旧hashmap迁移到新hashmap。

为什么扩容后的大小要是二次幂?

1)在迁移的时候,会根据key重新计算hashcode,重新获取新的index。此时如果最大容量每次都是2的二次幂,那么在计算index的时候(默认情况下),有50%的概率其位置不发生改变,可以与原数组保持一致。

2)同时,如果最大长度保持为二次幂,那么散列的会更均匀,如果不是二次幂,会导致某些位置永远不会被散列到,浪费地址空间。

3.关于重写equals必须要重写hashcode的辨析。

作者通过get_entry方法引出的这个问题,但是我觉得并不很合适,原因如下:

首先我们看代码:

final Entry<K,V> getEntry(Object key) {
            
        if (size == 0) {
            return null;
        }
        //通过key的hashcode值计算hash值
        int hash = (key == null) ? 0 : hash(key);
        //indexFor (hash&length-1) 获取最终数组索引,然后遍历链表,通过equals方法比对找出对应记录
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && 
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }    

通过代码可以看到,在获取元素的时候,首先是根据key计算hashcode,然后根据hashcode找到index,之后进行两个判断

1)hashcode是否相等

2)key是否equal

作者提到,这里有些人会认为再次判断hashcode是否相等多此一举,仅通过equals即可,这是不对的。但是作者后面又说这和重写equals没重写hashcode相关,因为只重写equals不重写hashcode,那么equals可能相等,但是hashcode不等,此时按照Object的HashCode约定,不能返回元素。

我认为这里说的是对的,但是不够清晰。为了讲清楚,我们把其分为两中情况。

1)hashcode和equals都不重写,此时二者比较的都是key的地址(如果key是对象)

此时对于某一次get,可以得到一个hashcode,通过hashcode,得到index,然后进行判断

1】hashcode是否相等

2】key是否equal

此时,如果舍弃判断1】,我们会发现,因为此时equals和hashcode等价,舍弃其中任何一个都不会违背Object的HashCode约定。

2)重写equals,不重写hashcode

此时对于某一次get,可以得到一个hashcode,通过hashcode,得到index,然后进行判断

1】hashcode是否相等

2】key是否equal

此时,如果舍弃判断1】,我们会发现,因为此时equals和hashcode不等价,同时因为index是由hashcode计算出来的,不同的hashcode可能得到同样的index,没有判断1】,得到的返回值的hashcode不一定等,但是因为内容相同,可以得到返回值,此时得到的返回值是不符合Object的HashCode约定,该约定要求hashcode的范围一定要比equals大。

4.关于为什么重写equals必须要重写hashcode

如果不重写,我们会发现,在hashmap的主干(数组)上的key-value对key可能相等,但是因为hashcode不等,得到的index也不等,因为计算hashcode用的是地址,不是值。按照要求,此时应该出现hash冲突。这也导致key正确,但是定位不到正确的位置,得到正确的值,得到null。

【讲得不好,后续接着改】

5. JDK1.8中HashMap的性能优化

链表>=8,数组长>=64,链表变红黑树。

 文章来源地址https://www.toymoban.com/news/detail-615786.html

到了这里,关于Java集合之一——HashMap(辨析)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JavaSE专栏53】Java集合类HashMap解析,基于哈希表的键值对存储结构

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了 Java 中集合类 HashMap 的语法、使用说明和应用场景,并给出了样例代码。

    2024年02月15日
    浏览(40)
  • 如何遍历HashMap集合?

    在Java中,HashMap是一种常用的数据结构,它提供了快速的查找、插入和删除操作。当我们需要遍历HashMap中的所有元素时,可以利用三种不同的方法实现。 HashMap中存储的是键值对的形式,因此最简单的方法就是直接遍历键值对。我们可以通过以下代码实现: 上述代码中,我们

    2023年04月23日
    浏览(43)
  • JavaSE进阶 | Map集合、HashMap集合、TreeMap集合

    目录 🏀Map集合概述  🥅Map接口常用的方法 🥅哈希表(散列表)数据结构 🥅同时重写HashCode和equals 🥅HashMap和Hashtable的区别 🥅Properties类 🥅TreeSet(TreeMap)集合 🥅自平衡二叉树数据结构 🥅实现比较器接口 🥅集合工具类Collections (1) Map和Collection没有继承关系,是一个平级的

    2023年04月09日
    浏览(43)
  • HashMap集合万字源码详解(面试常考)

    散列,又称哈希(Hash),是一种数据处理方式。它通过特定的算法,将输入(比如字符串、文件等)转换成固定长度的一串(通常是数字),并且这个过程是不可逆的。这个过程中的算法就称为哈希函数,得到的结果就称为哈希值。 散列的主要作用是为了检索数据。通过散

    2024年02月02日
    浏览(42)
  • Map集合体系(HashMap,LinkedHashMap,TreeMap)

    目录 1.Map集合 2.hashMap集合 3.LinkedHashMap集合 4. TreeMap集合 1.Map集合         Map集合是键值对集合         格式:{key1=value1, key2=value2, key3=value3, ...}         Map系列集合的特点都是由键决定的,值只是一个附属品,值不做要求 2.实现类有哪些?,各自有什么特点?  

    2024年02月21日
    浏览(41)
  • 一篇文章,轻松拿捏大厂必问的HashMap源码分析

    目录 一,JDK8之后HashMap的新特性 二,hashMap源码属性解读 (一),默认初始化容量数量:16 (二),最大数组容量:2^30 (三),默认负载因子:0.75f (四),触发树化条件1,链表阈值: (五),解树化的阈值:  (六),触发树化条件二,hash桶阈值(数组元素个数): 三

    2023年04月08日
    浏览(83)
  • Rust 笔记:Rust 语言中哈希结构(哈希映射,HashMap)、集合(哈希集,HashSet)及其使用

    Rust 笔记 Rust 语言中映射(HashMap)与集合(HashSet)及其用法 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/130876735 【介绍】:本文介绍 Rust 中哈希结构相关概念及其使用。在 R

    2024年02月09日
    浏览(53)
  • 第12章_集合框架拓展练习(ArrayList,HashSet,TreeSet,HashMap,斗地主,省市联动)

    1、随机验证码 随机验证码。 随机生成十组六位字符组成的验证码。 验证码由大小写字母、数字字符组成。 代码实现,效果如图所示: 开发提示: 使用字符数组保存原始字符,利用Random类生成随机索引。 将十组验证码放到集合中 用Iterator迭代器遍历集合 2、学生信息录入

    2024年01月17日
    浏览(46)
  • JavaEE 初阶篇-线程安全的集合类、多线程环境使用 ArrayList、队列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的区别)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 线程安全的集合类         1.2 线程安全的集合类 - Vector         1.3 线程安全的集合类 - Stack         1.4 线程安全的集合类 - HashTable         2.0 多线程环境使用 ArrayList        

    2024年04月25日
    浏览(51)
  • Java进阶(HashMap)——面试时HashMap常见问题解读 & 结合源码分析

    List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中HashMap集合的面试问题,结合源码分析题目背后的知识点。 关于List的博客文章如下: Java进阶(List)——面试时List常见问题解读 结合源码分析 关于的Set的博客文章如下: Jav

    2024年02月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包