【面试官】HashMap为什么线程不安全?

  • 面试官:你说下HashMap的内部结构?
  • 面试官:那一个键值是怎么存储到HashMap的?
  • 面试官:HashMap链表还会转换成什么?
  • 面试官:HashMap为什么线程不安全?
  • 面试官:有线程安全的Map吗?
  • 面试官:HashTable和ConcurrentHashMap有什么区别吗?
  • 👉以【面试官面试】形式覆盖Java程序员所需掌握的Java核心知识、面试重点
  • 📚本期是《Java系列》,其他系列博客请订阅专栏《Java Offer训练营》
  • ❤创作不易,不妨点赞、收藏、关注支持一下

文章目录

  1. HashMap内部结构
    1. 键值的添加流程
    2. 红黑树
  2. 线程安全的Map
    1. 线程不安全的HashMap
    2. 线程安全的ConcurrentHashMap
    3. HashTable和ConcurrentHashMap

1. HashMap内部结构

面试官:你说下HashMap的内部结构?

好的面试官。

HashMap内部存储数据的对象是一个实现Entry接口的Node数组,也称为哈希桶transient Node<K,V>[] table,后面我们称Node数组为Entry数组。Entry数组初始的大小是16

Node节点的内部属性key、value分别代表键和值,hash代表key的hash值,而next则是指向下一个链表节点的指针。

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}

1.1 键值的添加流程

面试官:那一个键值是怎么存储到HashMap的?

首先会调用hash方法计算key的hash值,通过key的hashCode值与key的hashCode高16位进行异或运算,使hash值更加随机与均匀。

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

再通过该hash值与Entry数组的长度相与,得到要存储到的索引位置int index = (table.length - 1) & hash。如果该索引位置是空的,会把键值直接添加到表头,如果哈希冲突了则会用链表法形成一条链表。

数据添加后,会判断当前容量是否到达了threshold阈值,threshold等于负载因子loadFactor * table.length。负载因子默认是0.75,threshold第一次扩容时为0.75 * 16 = 12

如果到达阈值了则会对Entry数组进行扩容,扩容成为原来两倍容量的Entry数组。

1.2 红黑树

面试官:HashMap链表还会转换成什么?

当链表长度 >= 8时,会把链表转换为红黑树

是这样的,HashMap的链表元素如果数量过多,查询效率会越来越低,所以需要将链表转换为其他数据结构。而二叉搜索树这种数据结构是绝对的子树平衡,左节点比父节点小,右节点比父节点大,在极端情况会退化为链表结构

而红黑树放弃了绝对的子树平衡,转而追求的是一种大致平衡,在极端情况下的数据查询效率更优。

stat

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java Offer训练营 文章被收录于专栏

👉以贴近现实的【面试官面试】形式帮助你系统学习后端技术 👉成体系知识帮你在后端进阶,每一道问答助你怒怼大厂面试官,收获大厂offer 👉《Java Offer训练营》包含Redis系列、MySQL系列、Kafka系列、ZooKeeper系列、JVM系列、多线程系列等等 👉制作不易,各位的支持是我创作的最大动力

全部评论
666
点赞
送花
回复
分享
发布于 04-25 23:36 广东
支持
点赞
送花
回复
分享
发布于 05-06 20:49 广东
滴滴
校招火热招聘中
官网直投

相关推荐

部门氛围好,不卷,欢迎投递!
投递蚂蚁集团等公司10个岗位 >
点赞 评论 收藏
转发
3 6 评论
分享
牛客网
牛客企业服务