
HashMap是Java面试的“保留曲目”几乎每场必问。但面试官不会只问“底层是什么”而是连环追问一层比一层深。你能扛到第几轮来试试。第一轮底层数据结构是什么“数组链表红黑树。” 这是送分题。JDK 1.8之后链表长度超过8且数组长度≥64时转红黑树退化阈值是6。为什么是8因为泊松分布下链表长度到8的概率不到千万分之一再长就是hash冲突严重了。答出这些第一轮稳过。第二轮扩容机制讲一下“默认容量16负载因子0.75扩容2倍。1.7头插法1.8尾插法。” 面试官点头接着问“为什么负载因子是0.75” 如果你说“空间和时间权衡”算及格如果能说出“0.75时冲突概率和空间利用率平衡且容量是2的幂时0.75正好是3/4扩容后元素分布更均匀”那就能进入下一轮。第三轮hash函数怎么设计的“(h key.hashCode()) ^ (h 16)。” 面试官追问“为什么要异或高16位” 这是扰动函数让高16位也参与运算减少hash冲突。因为数组索引是(n-1)hashn-1的高位都是0如果不扰动高16位就浪费了。能答到这里已经超过一半候选人。第四轮线程安全吗“不安全。1.7扩容时头插法会导致死循环1.8改成尾插法但并发put仍会数据覆盖。” 面试官接着问“那ConcurrentHashMap怎么解决的” 1.7用分段锁Segment1.8用CASsynchronized锁单个桶。能对比着说清楚第四轮通过。第五轮为什么容量总是2的幂“因为(n-1)hash等价于hash%n但位运算更快。而且2的幂减1后二进制全是1能保证索引分布均匀。” 面试官追问“如果初始化时传入17会怎样” 会调用tableSizeFor向上取到32。能说出这个方法名和逻辑第五轮拿下。第六轮红黑树转换条件为什么是8和64“链表长度≥8且数组长度≥64才转树否则先扩容。因为数组太小时扩容比转树更高效避免频繁树化。” 面试官再问“为什么退化是6不是7” 为了避免频繁转换6和8之间留缓冲。能答出“避免抖动”第六轮过关。第七轮fail-fast机制了解吗“modCount记录修改次数迭代时检查不一致就抛ConcurrentModificationException。” 面试官问“怎么安全遍历” 用Iterator.remove()或并发容器。第七轮已经进入源码级。第八轮如果key是可变对象会怎样“hashCode和equals必须重写。如果key修改后hashCode变了就再也找不到。比如用List做key修改元素后put进去get会返回null。” 面试官满意地点头第八轮通过。第九轮手写一个简易HashMap到这一轮面试官想看你的设计能力。数组链表hash扰动扩容get/put逻辑。能写出来且边界处理正确第九轮封神。第十轮为什么1.8改成尾插法“头插法在并发扩容时可能形成环形链表尾插法避免死循环但并发put仍不安全。” 能答到第十轮你已经是面试官眼中的“源码级选手”。大多数人扛到第三轮就卡壳准备充分的到第六轮真正能扛到第八轮以上的少之又少。HashMap的连环问考的不是背诵而是对数据结构、并发、源码设计的理解。下次面试前别只背“数组链表”把扰动函数、扩容、树化、并发问题串成一条线。能扛到第几轮取决于你挖得有多深。