什么是Hashmap?

HashMap 是一个关联数组、哈希表,它是线程不安全的,允许key为null,value为null。遍历时无序。

在JDK8中,当链表长度达到8,会转化成红黑树,以提升它的查询、插入效率,它实现了Map<K,V>, Cloneable, Serializable接口。

因其底层哈希桶的数据结构是数组,所以也会涉及到扩容的问题。

当HashMap的容量达到threshold域值时,就会触发扩容。扩容前后,哈希桶的长度一定会是2的次方。
这样在根据key的hash值寻找对应的哈希桶时,可以用位运算替代取余操作,更加高效。

数组:      内存中的一片连续区域,同类型数据的集合,有索引,查询快,增删慢,不可扩容。

链表:   不连续的区域,每个节点放值和指向下一个节点的指针。查询慢,增删快

哈希表:  可以理解位数组和链表的组合。即一个一维数组,但是数组中的每个元素是一个链表

HashMap常量:

    1.DEFAULT_INITIAL_CAPACITY    //默认初始化的容量时16,必须是2的幂次方。

    2.MAXIMUM_CAPACITY      //最大容量:最大的容量是2^30。

    3.DEFAULT_LOAD_FACTOR = 0.75f  //默认的负载因子是0.75

    4.TREEIFY_THRESHOLD = 8    //一个桶中bin的存储方式由链表转换成树的阈值。即当桶中bin的数量超过TREEIFY_THRESHOLD时使用树来代替链表。默认值是8

    5.UNTREEIFY_THRESHOLD = 6  //当执行resize扩容操作时,当桶中bin的数量少于UNTREEIFY_THRESHOLD时使用链表来代替树。默认值是6 。

    6.MIN_TREEIFY_CAPACITY     //当桶中的bin被树化时最小的hash表容量

成员变量:

1.transient Node<K,V>[] table; //这个数组在首次使用时初始化,并根据需要调整大小。分配空间时,长度始终是2的幂次方。   

  • table是一个用于存放键值对的数组。
  • 第一次使用(插入元素)时被初始化,根据需要可以重新分配空间(扩容: 因为规定容量是2的幂,所以扩容时把原容量乘2.)。
  • 分配的空间长度必须是2的幂次方。

2.transient Set<Map.Entry<K,V>> entrySet;  //当被调用entrySet时被赋值。通过keySet()方法可以得到Map中的key集合,通过values可以得到Map中的value集合。

3.transient int size;    //该值用于存放Map中键值对的个数。

4.transient int modCount;  //HashMap被结构性修改的次数

5.int threshold;      //阈值,当HashMap中的键值对数量超过了阈值,就会扩容。thresold = capacity * loadFactor

6.final float loadFactor;    //负载因子

 

HashMap共包括4个构造函数:


      public HashMap()// 默认构造函


      public HashMap(int initialCapacity, float loadFactor) / /指定“容量大小”和“加载因子”的构造函数


      public HashMap(int initialCapacity) // 指定“容量大小”的构造函数


      public HashMap(Map<? extends K, ? extends V> m) // 包含“子Map”的构造函数,将m中的全部元素逐个添加到HashMap中

哈希冲突的解决方法:1.开放地址法  2.链地址法  3.公共溢出法  4.再哈希法

 

为什么HashMap线程不安全?

HashMap会进行resize操作,在resize操作的时候会造成线程不安全。

1. put的时候导致的多线程数据不一致  

2. HashMap的get操作可能因为resize而引起死循环

HashMap线程不安全应该怎么解决?

1.使用HashTable替代HashMap  //一个线程访问HashTable的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。

2.类ConcurrentHashMap定义Map  //ConcurrentHashMap是JUC包中的一个类,方法内部使用了synchronized保证线程安全。

3.Collections类的synchronizedMap(Map m)方法可以返回一个线程安全的Map

 

HashMap跟Hashtable的区别?

HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主 要区别在于 HashMap 允许空(null)键值(key),由于非线程安全,在只有一个线程访问 的情况下,效率要高于 Hashtable。

1.历史原因:Hashtable 是基于陈旧的 Dictionary 类的,HashMap 是 Java 1.2引进的 Map 接口的一个实现

2.同步性:Hashtable 是线程安全的,也就是说是同步的,而 HashMap 是线程序不安全的, 不是同步的

3.值:只有 HashMap 可以让你将空值作为一个表的条目的 key 或 value

posted @   jakub  阅读(424)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示