hashmap是什么?
它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap
hashmap如何存储?
hashmap = 数组 + 链表 + 红黑树
hashmap使用链地址法解决哈希冲突,hashmap中最重要的成员变量就是Node数组,Node中包含键值对,hash冲突时指向下一条数据的指针以及key的hash值。
transient Node<K,V>[] table;
ps:被transient关键词修饰的成员变量在自动序列化对象时会被忽略,静态成员变量也会被忽略。
hashmap如何计算key值的下标?
源码如下:
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); // >>> 无符号右移,忽略符号位,空位都以0补齐 } p = tab[i = (n - 1) & hash]
因此,hashmap计算key值在Node数组中下标过程为:
1. 获取key值的hashcode 2. 计算hash值:hashcode低16位与高16位进行异或运算得到hash值 3. 计算下标:截取hash值低位作为下标
一个奇怪的知识点:
如果b的值为2的n次方的时候(n为自然数),可以用位运算来替代模运算, 转化如下:、
a % b = a & (b-1) //jdk1.7中使用 h & (length-1) 来计算下标
hashmap如何扩容?
hashmap每次扩容都会将数组扩大为原来的二倍,键值对在新数组中的下标=原数组下标 or 原数组下标+扩容后数组容量除以2
参考博客:https://www.jianshu.com/p/30bffabb2e5c