前言
本文阐述了以下关于HashMap的知识点
- 整体结构
- put 简化逻辑,数组下标哈希计算
- JDK 1.7 与 JDK 1.8的对比
- HashMap的扩容机制
- HashMap是线程非安全的
- 其它扩展
HashMap的数据结构
HashMap的底层是拉链法,即用数组+链表相结合的数据结构,JDK 1.8后引入了 红黑树
而每一个键值对其实都是一个节点,这种节点是一个 Entry 对象
class Entry<K, V> {
private K k;
private V v;
private Entry next;
public Entry(K k, V v, Entry next) {
this.k = k;
this.v = v;
this.next = next;
}
public K getK() {
return k;
}
}
put 逻辑
往Map中插入一个元素,HashMap是如何拿到下标的呢?
在Java 1.7中,put(key, value) 的源码中有以下两行
int hash = hash(key);
int i = indexFor(hash, table.length);
首先将传进来的 key 进行 hash(key) 得到一个 hash 值,再通过 indexFor 算法算出数组下标 i
get同样需要用到这两行代码来获取 key 的数组下标
接下来我们演示下,编译下列代码
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("水果","苹果");
hashMap.put("蔬菜","菠菜");
hashMap.put("主食","米饭");
hashMap.put("肉类","鸡肉");
hashMap.put("酒水","红酒");
hashMap.put("餐具","刀叉");
for (String key: hashMap.keySet()) {
int hashCode = key.hashCode();
int index = hashCode % 8;
System.out.println(key + "的hashCode是" + hashCode);
}
蔬菜 的hashCode是 1090608, index是 0
酒水 的hashCode是 1180962, index是 2
肉类 的hashCode是 1051922, index是 2
水果 的hashCode是 885224, index是 0
餐具 的hashCode是 1235559, index是 7
主食 的hashCode是 659972, index是 4
可以看到