首页 > 其他分享 >Map集合之HashMap细说

Map集合之HashMap细说

时间:2024-06-22 20:30:25浏览次数:6  
标签:扩容 Map 下标 HashMap 链表 线程 细说 hash 函数

        最近在看面试题,看到了hashmap相关的知识,面试中问的也挺多的,然后我这里记录下来,供大家学习。

Hashmap为什么线程不安全

  • jdk 1.7中,在扩容的时候因为使用头插法导致链表需要倒转,从而可能出现循环链表问题或者数据丢失的问题

  • jdk 1.8中,在put方法中,假设A,B两个线程都插入相同的值到同一个下标,这个下标对应的值此时为null,假设线程A进行方法后挂起,而线程B顺利执行,此时该下标对应的值为B插入的值,然后A线程获得时间轮,此时线程A不再进行hash判断了,直接进行插入,就会导致覆盖了原来B插入到该下标的值

HashMap类(底层为数组+链表+红黑树)

扩容机制

        在java8以后,满足扩容机制的只需要笑傲一个条件即可,即当加入的新的数据和其他数据大于或者等于阈值就会发生扩容,且这种扩容形式也是在先插入新值后,再进行扩容。

        在java7中,每个节点存放一个Entry,每个Entry后面跟着一个链表,链表的每个节点存放一个Entry,这个Entry上保存有相应的key/Value,且存放着下一个节点的地址;在java8之后,因为引入了红黑树,所以把Entry改成了Node,其他的存放的内容都和Entry上面存放的一样。

        但是,在java8后虽然底层结构变成了数组+链表+红黑树,但是不一定会用到红黑树,只有当总的数据量大于64或者链表长度大于8的时候会将链表转换为红黑树。

扩容满足的条件(什么时候扩容)

在java7中,扩容需要满足以下两个条件(任意一个满足都会发生扩容)

  • 存放当前元素前,数据个数大于等于阈值

  • 存放当前元素时发生hash冲突

在java8后,扩容只需要满足--》存放当前元素后,数据量大于等于阈值,且扩容是在插入新数据后进行扩容

为什么在JDK 1.8后hashmap底层要添加红黑树

        当hash冲突过多的时候,数据插入到链表后面就会越来越多,就会导致链表链化严重,对于CRUD这些操作会造成较高的复杂度(O(n)),所以为了解决这一问题,在java8后使用红黑树来处理这种链化的情况。

hash冲突怎么解决

        hash冲突表示的是当插入一个新值的时候通过hash函数计算出的下标值已经存入得对应数据,这个时候再插入一个值的时候就会出现hash冲突。

开放地址法
线性探测

        根据hash函数计算下标值,如果当前下标已经有值存在,那就去判断下一个下标是否存值,通过这样的方式来解决hash冲突,但是这样的方式可能会引起聚集,即连续找了多次下标都是有值的情况,这样会在后续的操作中增加复杂度。

二次探测

即根据hash下标的二次方进行探测(1,4,9.......),这样的做法可以减少聚集的问题

双重散列

        如果当前通过hash散列函数计算出的下标已经存入了值,那就在用另外的hash散列函数再次进行计算

链地址法

        每一个hash桶后面都会跟着一个链表,当通过hash函数找到对应桶,如果当前值对应下标在链表中已经存入了值,那么就会将该值放在链表末尾然后进行存储。

再哈希

       再哈希是指当前的哈希函数计算出来的下标值已经被占用,这时就会使用一个新的哈希函数来进行再次计算。

双重散列和再哈希的区别

        双重散列和再哈希都是需要使用多个hash函数来解决hash冲突,但是对于双重散列而言,每一次的hash函数都是新的hash函数,不会根据前一个hash函数计算出来的下标值为基础进行计算,而再哈希的每一个hash函数会根据前一个hash函数计算出来的下标值为基础进行计算,这样对于下一次计算出来的下标肯定不会和前一个hash函数计算出来的下标相重合。

hashmap和hashtable的区别

  • hashmap是线程不安全的,而hashtable是线程安全的

  • hashmap可以存储null键和null值,hashtable不能存储null键和null值

  • hashmap在jdk1.8之后底层结构为数组+链表+红黑树,hashtable底层数据结构为数组+链表

以上为自己学习过程中列出来的知识点,当然还存在很多不足,各位有补充的可以在评论区进行留言我们共同学习~

标签:扩容,Map,下标,HashMap,链表,线程,细说,hash,函数
From: https://blog.csdn.net/qq_71416673/article/details/139887321

相关文章

  • Java 面试题:如何保证集合是线程安全的? ConcurrentHashMap 如何实现高效地线程安全?
    在多线程编程中,保证集合的线程安全是一个常见而又重要的问题。线程安全意味着多个线程可以同时访问集合而不会导致数据不一致或程序崩溃。在Java中,确保集合线程安全的方法有多种,包括使用同步包装类、锁机制以及并发集合类。最简单的方法是使用Collections.synchronized......
  • MapReduce和YARN
    一:MapReduce概述MapReduce是hadoop三大组件之一,是分布式计算组件Map阶段:将数据拆分到不同的服务器后执行Maptask任务,得到一个中间结果Reduce阶段:将Maptask执行的结果进行汇总,按照Reducetask的计算规则获得一个唯一的结果我们在MapReduce计算框架的使用过程......
  • 全网最好看的单细胞umap图绘制教程
    作者按大家或许都曾被Nature,Science上的单细胞umap图吸引过,不免心生崇拜。在这里,我们将介绍一种简单方便的顶刊级umap图可视化全文字数|预计阅读时间:2000|5min——Starlitnightly(星夜)环境加载我们先导入一些必须的依赖包importomicverseasovimportscanpyassci......
  • ES6 新增Set 和 Map 两种数据结构
    ES6新增了Set和Map这两种数据结构,它们为JavaScript提供了更强大和灵活的数据处理能力。下面详细介绍一下Set和Map的特性和用法:SetSet是一种类似于数组的数据结构,但是成员的值都是唯一的,没有重复的值。特性:Set中的元素是唯一的,不会出现重复的值。Set可以接......
  • java中Optional的应用,以及map和flatMap的区别
    关于Option的介绍可以看深入理解java8中的Optional类就可以了,但是复杂一点的使用在网上却没有搜到,这里结合我开发时遇到的真实案例来讲一下Option的使用。1.案例一在真实业务操作过程中,都是对象里面套对象,这边先简单定义操作对象:publicclassPictureCondition{privateStri......
  • ConcurrentHashMap(并发工具类)
    并发工具类在JDK的并发包里提供了几个非常有用的并发容器和并发工具类。供我们在多线程开发中进行使用。5.1ConcurrentHashMap5.1.1概述以及基本使用在集合类中HashMap是比较常用的集合对象,但是HashMap是线程不安全的(多线程环境下可能会存在问题)。为了保证数据的安全性我......
  • Map集合的特点以及遍历方式
    文章目录前言一、认识Map集合二、Map集合体系体系图Map集合体系的特点三、Map集合常用方法四、Map集合的遍历遍历方式一遍历方式二遍历方式三五、HashMap底层原理HashMap的特点六、LinkedHashMap底层原理LinkedHashMap的特点七、TreeMap底层原理TreeMap的特点总结......
  • 离线使用端口扫描工具Nmap和Netcat
    1.安装nmap命令Centos7+系统离线安装nmap命令链接:https://pan.baidu.com/s/1jqNbRNpctXgUfa4Qfpu4Pg提取码:0124rpm-ivh  *********.rpm2.进行端口扫描使用Nmap扫描目标主机,例如扫描本地主机localhost: sudonmap-sS-p-localhost-sS:使用TCPSYN扫描。-p-:......
  • Nmap
    NMap使用技巧总结一、主机发现全面扫描/综合扫描nmap-A192.168.1.103Ping扫描nmap-sP192.168.1.1/24免Ping扫描,穿透防火墙,避免被防火墙发现nmap-P0192.168.1.103TCPSYNPing扫描nmap-PS-v192.168.1.103nmap-PS80,10-100-v192.168.1.103(针对防火墙丢......
  • SQLMAP使用参数
    get型常用参数-u:指定注入的URLsqlmap-uURL--dbs:爆出所有数据库sqlmap-uURL--dbs--dbms:指定数据库类型sqlmap-uURL--dbms=mysql--users:查看数据库的所有用户sqlmap-uURL--users--current-user:查看数据库当前用户sqlmap-uURL--current-user--current-db:......