HashMap源码前前后后看了好几次,也和同事分享过好几次,每次都有新的收获。
分享也是一种提高!
本文首写于个人云笔记(点击访问),经多次修改,短期内不会有重大修改了,现发于此,有任何问题欢迎交流指正。
本文最初借鉴于http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html,其基于jdk1.6,自己分析jdk1.8后,发现有很大的不同,遂记录于此。
Java最基本的数据结构有数组和链表。数组的特点是空间连续(大小固定)、寻址迅速,但是插入和删除时需要移动元素,所以查询快,增加删除慢。链表恰好相反,可动态增加或减少空间以适应新增和删除元素,但查找时只能顺着一个个节点查找,所以增加删除快,查找慢。有没有一种结构综合了数组和链表的优点呢?当然有,那就是哈希表(虽说是综合优点,但实际上查找肯定没有数组快,插入删除没有链表快,一种折中的方式吧)。一般采用拉链法实现哈希表。
JDK1.6中HashMap采用的是位桶+链表的方式,即我们常说的散列链表的方式;JDK1.8中采用的是位桶+链表/红黑树的方式,也是非线程安全的。当某个位桶的链表的长度达到某个阀值的时候,这个链表就将转换成红黑树。
1.1 所属包:package java.util;
1.2 导入包:
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
1.3定义:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {}
2、HashMap的部分属性
private static final long serialVersionUID = 362498820763181265L;
//The default initial capacity - MUST be a power of two.
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //jdk1.6直接写16,这效率更快??
// The maximum capacity,MUST be a power of two <= 1<<30.
static final int MAXIMUM_CAPACITY = 1 << 30; // 2的30次方
static final float DEFAULT_LOAD_FACTOR = 0.75f; //填充比,装载因子
/**(jdk1.8新加)
* The bin count threshold for using a tree rather than list for a
* bin.当add一个元素到某个位桶,其链表长度达到8时将链表转换为红黑树.
* 2< value<=8 时to mesh with assumptions in tree removal about conversion back to plain bins upon shrinkage.
*链表转为树,binCount>=TREEIFY_THRESHOLD-1,-1 for 1st。
*/ //当某个桶中的键值对数量大于8个【9个起】,且桶数量大于等于64,则将底层实现从链表转为红黑树
// 如果桶中的键值对达到该阀值,则检测桶数量static final int TREEIFY_THRESHOLD= 8; //jdk1.8新加
//太小则转为链表
tab[index] = loHead.untreeify(map);
static final int UNTREEIFY_THRESHOLD = 6; //jdk1.8新加
static final int MIN_TREEIFY_CAPACITY = 64; //jdk1.8新加
/* ---------------- Fields -------------- */
// jdk1.6 为 transient Entry[] table;
transient Node<K,V>[] table; //存储元素(位桶)的数组,length power of two
transient Set<Map.Entry<K,V>> entrySet;
transient int size; // key-value对,实际容量
transient int