1. 基本概念
public class HashMap<K,V> {
transient Node<K,V>[] table;
int threshold;
final float loadFactor;
int size;
}
graph TD
A[HashMap] --> B[数组 + 链表]
B --> C[数组]
B --> D[链表]
B --> E[红黑树]
C --> F[散列分布]
D --> G[解决冲突]
E --> H[优化查询]
2. 数据结构
Node<K,V>[] table;
static class Node<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent;
TreeNode<K,V> left;
TreeNode<K,V> right;
boolean red;
}
3. 重要参数
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;
4. 核心方法
public V put(K key, V value) {
int hash = hash(key);
int index = (n - 1) & hash;
if (node == null) {
} else {
}
}
public V get(Object key) {
Node<K,V> e = getNode(hash(key), key);
return e == null ? null : e.value;
}
5. 重要机制
5.1 哈希计算
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
5.2 扩容机制
final Node<K,V>[] resize() {
}
6. 面试回答要点
6.1 基本介绍
HashMap 是基于哈希表实现的 Map 接口,特点是:
1. 存储键值对
2. 允许 null 键和 null 值
3. 非线程安全
4. 无序
6.2 数据结构
1. 数组 + 链表 + 红黑树
2. JDK 1.8 引入红黑树优化
3. 链表长度超过 8 转红黑树
4. 红黑树节点少于 6 转链表
6.3 重要参数
1. 初始容量:16
2. 负载因子:0.75
3. 扩容阈值:容量 * 负载因子
4. 树化阈值:8
6.4 工作原理
1. 计算 key 的 hash 值
2. 定位数组索引:(n-1) & hash
3. 解决哈希冲突:链表或红黑树
4. 动态扩容:翻倍扩容
7. 性能优化建议
HashMap<K,V> map = new HashMap<>(initialCapacity);
@Override
public boolean equals(Object o) {
}
@Override
public int hashCode() {
}
8. 常见问题解答
8.1 为什么是 2 的幂容量?
1. 便于计算索引:(n-1) & hash
2. 散列更均匀
3. 扩容时重哈希更高效
8.2 为什么使用红黑树?
1. 链表查询 O(n)
2. 红黑树查询 O(log n)
3. 平衡树,性能稳定
8.3 线程安全问题
1. HashMap 非线程安全
2. 可使用 ConcurrentHashMap
3. 或 Collections.synchronizedMap()
9. 实际应用示例
HashMap<String, User> userMap = new HashMap<>();
userMap.put("user1", new User("张三"));
User user = userMap.get("user1");
for (Map.Entry<String, User> entry : userMap.entrySet()) {
String key = entry.getKey();
User value = entry.getValue();
}
for (String key : userMap.keySet()) {
}
for (User value : userMap.values()) {
}