android hashmap面试题,HashMap 源码解析与面试题整理

本文详细剖析HashMap的底层原理,包括基于链表和红黑树的实现、put操作流程、扩容策略以及哈希碰撞的处理方法。讨论了HashMap与HashTable的区别,以及为何ArrayList取数更快的原因。涉及技术点有:线程不安全性、哈希算法、链表与红黑树转换、扩容resize()过程和哈希冲突解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码解析不会通篇解析,会通过面试题整理来针对性地解析其中的关键点

主要的几个面试题:

HashMap的底层原理是什么?线程安全么?

HashMap中put是如何实现的?

谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的?

什么是哈希碰撞?怎么解决?

HashMap和HashTable的区别

HashMap中什么时候需要进行扩容,扩容resize()是如何实现的?

hashmap concurrenthashmap原理

arraylist和hashmap的区别,为什么取数快?

1. HashMap的底层原理是什么?线程安全么?

HashMap的底层原理是链表的数组, 通过hash算法计算出 key的hash值再根据数组长度取模得到index 如果index相同,那么就排在同一个链表中。链表中根据key的hash值大小有序排列方便查找

2858fbee58be

内部结构

jdk 1.8 之后 androidsdk 24 之后 hashmap 的内部实现有链表改为 链表加红黑树实现,当一个链表的长度大于 8之后将会在后续添加的时候转变为红黑树

2858fbee58be

红黑树

get: 先通过hash算法计算出key的hash值 然后再通过hash根据 链表数组的长度取模 获得index。根据index去循环链表或者红黑树取到相应的value。

put: 先通过hash算法计算出key的hash值 然后再通过hash根据 链表数组的长度取模 获得index,再根据排列顺序将 entry放到链表或者红黑树中。

线程不安全,当多个线程操作的时候可能使读取的数据为错误数据。

2. HashMap中put是如何实现的?

简单过程:先通过hash算法计算出key的hash值 然后再通过hash根据 链表数组的长度取模 获得index,再根据排列顺序将 entry放到链表或者红黑树中。

看代码:

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

boolean evict) {

Node[] tab; Node p; int n, i;

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

// Step 1 获取hashmap中链表数组的长度(其中包含了一个重要的步骤 resize 之后在沟通)

if ((p = tab[i = (n - 1) & hash]) == null)

// 此处 p指向了tab数值中对应index元素链表的头结点

tab[i] = newNode(hash, key, value, null);

// Step 2 对key值的hash对 长度取模 ( (n - 1) & hash 等价于 hash % n ,此处采用位运算是为了性能考虑)得到i。

// 再检查数组i元素是否存在,如果不存在将node 赋值

else {

Node e; K k;

if (p.hash == hash &&

((k = p.key) == key || (key != null && key.equals(k))))

// Step 3 如果key相同 用e标记,指向p,后面将会把新的value 赋值给p节点

e = p;

else if (p instanceof TreeNode)

// 如果链表开始就是 树结构的 那么用树结构的逻辑将节点保存

e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);

else {

for (int binCount = 0; ; ++binCount) {

if ((e = p.next) == null) {

p.next = newNode(hash, key, value, null);

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

treeifyBin(tab, hash);

break;

}

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;

}

}

if (e != null) { // existing mapping for key

V oldValue = e.value;

if (!onlyIfAbsent || oldValue == null)

e.value = value;

afterNodeAccess(e);

return oldValue;

}

}

++modCount;

if (++size > threshold)

resize();

afterNodeInsertion(evict);

return null;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值