面试中如何回答HashMap的工作原理

使用过哪些地图类?有什么区别?HashMap是线程安全的吗?下载用的地图有哪些?他们

内部原理是什么,比如存储模式,hashcode,扩展,默认容量等。

为什么JAVA8的ConcurrentHashMap放弃了分段锁?有什么问题?如果你来设计,你会怎么做?

设计。

有没有顺序的Map实现类,如果有,它们是如何保证顺序的?

hashmap的实现原理,/mbshqqq b/article/details/79799009

以下是我自己的总结:

存储结构:

其中存储了一个条目数组,每个数组元素中的结构是一个条目链表。

Entry是map中的一个静态内部类,其中的变量有:key、value、hashcocd和next Entry。

哈希是什么?

也称为哈希,通过哈希算法将任意长度的输入转换为固定长度的输出,输出是哈希值。这是一个压缩映射,哈希值的空间通常比输出的空间小很多。不同的输入可能列出相同的输出,因此无法从哈希值中确定唯一的输入值。这也是为什么比较两个对象不能只用hashcode方法进行比较的原因。

哈希冲突:

对不同值进行哈希运算会生成相同的哈希值。这是不可避免的,但我们需要尽量减少其损失。

(1)设计的哈希算法使其尽可能均匀分布。

hashmap中哈希算法的分析

静态最终int哈希(对象键){

int h;

return (key == null)?0:(h = key . hashcode())^(h & gt;& gt& gt16);

}

让密钥的hashcode右移16位,以混合其高低位,增加低位的随机性,同时变相保持高位的特性。

计算元素位置的算法:

int index = hash & amp(数组.长度-1);

那么就很清楚为什么HashMap的数组长度是2的整数次方了。例如,如果初始长度为16,则16-1 = 15,15的二进制数为000000000000000000000165438。可以看出,基数二进制的最后一位必须是1。当使用哈希值执行AND时,最后一位可能是0或1。但是,偶数和哈希值之间的AND运算的最后一位必须是0,这导致一些位置永远不会映射值。

空值的处理

Hashmap接受空值,这些值放在数组的第一个元素中。当我把它们拿出来的时候我应该做什么?

hashmap是如何工作的?

里面有一个入口数组。放的时候我们先根据键值计算hashcode,然后计算元素在数组中的位置,把键值对封装在Map中。条目对象,然后将其存储在数组中。

如果有哈希冲突怎么办?

每个数组元素的位置都是一个链表结构,如果计算出来的hashcode相同,就把元素追加到链表中,这就是hashmap的处理方法。

取元素时,先计算键值对应的hashcode找到元素的位置,然后调用key的equals方法遍历链表,最后找到元素。

还有哪些解决哈希冲突的方法?

开放式寻址方法

这种方法也叫再散列法。其基本思想是:当关键字key的hash地址p=H(key)冲突时,基于P生成另一个hash地址p1,如果p1仍然冲突,则基于P生成另一个hash地址p2,直到找到一个不冲突的hash地址pi,并在其中存储相应的元素。

再散列方法

这种方法是同时构造几个不同的散列函数:

Hi=RH1(key) i=1,2,…,k

当哈希地址Hi=RH1(key)冲突时,计算hi = rh2 (key)...直到冲突不再发生。这种方法不易产生聚合,但增加了计算时间。

链地址法

这种方法的基本思想是将所有哈希地址为I的元素组成一个名为同义词链的单链表,并将单链表的头指针存储在哈希表的第I个单元中,因此查找、插入和删除主要在同义词链中进行。链地址法适用于频繁插入和删除。

建立一个公共溢出区

该方法的基本思想是将哈希表分为基本表和溢出表两部分,所有与基本表冲突的元素都填充在溢出表中。

默认负载系数为0.75

当贴图的大小超过当前容量的75%时,它将自动扩展,原始对象将放回新数组中。

再散列的过程是什么样的?

说白了就是先调整大小生成一个新的Entry数组,然后转移重新计算原数组中的值放入新数组,再把阈值改成新的length x load factor。

如果键为空,它将始终被散列到表[0]的桶中,即使在重新散列的过程中也是如此。非空键也可能被哈希到table[0]的位置,比如上图中的key = "f ",同样的键也可能在不同的时间被哈希到不同的位置,这与重哈希有关。

这个过程中容易出现哪些问题?

容易出现条件竞争。如果在扩展的过程中放入数据,会造成意想不到的结果。或者如果两个线程都触发容量扩展,也会有问题。

有没有遇到过这一块的好例子?

jdk1.8之后改为红黑树。为什么?说说红黑树的原理?

hashmap和hashtable有什么区别?

HashTable和HashMap的实现原理几乎一样,区别无非就是

HashTable不允许空键和值。

哈希表是线程安全的。

但是HashTable线程安全的策略代价太大,简单粗暴,get/put的所有相关操作都是同步的,相当于给整个哈希表加了一把大锁。

多线程访问时,只要有一个线程访问或操作对象,其他线程就只能阻塞,相当于把所有操作都序列化了,在竞争的并发场景下性能会很差。

篇幅有限,未完待续。