Java集合框架 Map接口实现类--HashMap源码分析 & HasmMap与HashSet的关系 & HashTable & Properties(HashTable 的
Posted Z && Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合框架 Map接口实现类--HashMap源码分析 & HasmMap与HashSet的关系 & HashTable & Properties(HashTable 的相关的知识,希望对你有一定的参考价值。
Map接口实现类:
1. HashMap源码分析
HashMap的数组table存储的就是一个个的Node<K,V>类型,很清晰地看到有一对键值,还有一个指向next的指针:
HashMap的无参构造方法,进入到该构造方法的源码查看一下:
- 发现没什么内容,只是赋值了一个默认加载因子;而在上文我们观察到源码中table和size都没有赋予初始值,说明刚创建的HashMap对象没有分配容量,并不拥有默认的16个空间大小,这样做的目的是为了节约空间,此时table为null,size为0。
当我们往map里添加元素时调用put方法:
- 这里面创建了一个tab数组和一个Node变量p,第一个if实际是判断table是否为空,而我们现在只关注刚创建HashMap对象时的状态,此时tab和table都为空,满足条件,执行内部代码,这条代码其实就是把resize()所返回的结果赋给tab,n就是tab的长度,resize顾名思义就是重新调整大小。查看resize()源码(部分)
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
if (oldCap > 0);
else if (oldThr > 0);
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
return newTab;
}
- 该方法首先把table及其长度赋值给oldTab和oldCap;threshold是阈值的意思,此时为0,所以前两个if先不管,最后else里newCap的值为默认初始化容量16;往下创建了一个newCap大小的数组并将其赋给了table,刚创建的HashMap对象就在这里获得了初始容量。然后我们再回到putVal方法,第二个if就是根据哈希码得到的tab中的一个位置是否为空,为空便直接添加元素,此时数组中无元素所以直接添加。至此HashMap对象就完成了第一个元素的添加。当添加的元素超过16*0.75=12时,就会进行扩容
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict){
if (++size > threshold)
resize();
}
- 扩容的代码如下(部分):
final Node<K,V>[] resize() {
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int newCap;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {//略}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
}
}
- 核心部分是else if里的移位操作,也就是说每次扩容都是原来大小的两倍。
- 注:额外说明的一点是在JDK1.8以前链表是头插入,jdk1.8及以后链表是尾插入。
小结:
- HashMap刚创建时,table是null,这么做是为了节省空间。当添加第一个元素时,table的容量会调整为16
- 当元素个数大于阈值(16 * 0.75 = 12 )时,会进行扩容,扩容的大小是原来的2倍。这么做的目的是为了减少调整扩容的次数,提升运行效率。
- jkd1.8 当链表长度大于等于8,并且元素个数大于等于64时,链表会调整成为红黑树,目的是提高执行效率。
- jkd1.8 链表元素个数小于等于6时,红黑树结构还原成链表。
- jdk1.8以前,链表时采用头插法,jdk1.8及以后以后采用尾插法。
2. HasmMap与HashSet的关系
-
点进去HashSet的构造方法,我们发现HashSet就是用HashMap实现的:
-
点进去HashSet的put方法,发现就是用的map的put方法(用map的key来保存数据):
3. HashTable
api文档:
4. Properties
api文档:
以上是关于Java集合框架 Map接口实现类--HashMap源码分析 & HasmMap与HashSet的关系 & HashTable & Properties(HashTable 的的主要内容,如果未能解决你的问题,请参考以下文章