注:基于JDK 1.8.0_131源代码为例进行分析

hashtable的结构图

hashtable采用桶位+链表结构实现。
jdk1.8中hashtable源码分析

hashtable的实现

采用的是“桶位”,即一个Entry数组实现:
jdk1.8中hashtable源码分析
Entry节点的实现:主要包括了key、value以及key的哈希值和next指向想一个节点。
jdk1.8中hashtable源码分析
说明:

  • 代码块1:为Entry节点中包含的key、value、hash、next。
  • 代码块2:为Entry的构造函数,即把新节点接在了next链表的开头部分。

相关参数规定

jdk1.8中hashtable源码分析
其中,threshold表示table数组扩容的节点数阈值;loadFactory为负载因子。

默认的数组大小,及负载因子:
jdk1.8中hashtable源码分析
Hasttable的默认容量(数组大小)为11,默认的负载因子为0.75。同时由代码块2可知数组扩容的阈值threshold=capacity*loadFactory。
注意:hashtable中的数组容量capacity没有限制为2的n次方,取任何大于0的数都行

Hashtable的put操作实现

jdk1.8中hashtable源码分析
说明:

  • 代码块1:hashtable之所以是线程安全的,原因为在put和get方法上使用synchronized关键字进行修饰。
  • 代码块2:限制了value不能为null
  • 代码块3:由于直接使用key.hashcode(),而没有向hashmap一样先判断key是否为null,所以key为null时,调用key.hashcode()会出错,所以hashtable中key也不能为null
  • 代码块4:hashtable中对hash值进行寻址的方法为hash%数组长度(与hashmap不同,所以不要求数组长度必须为2的n次方)。
  • 代码块5:entry=table[index]
  • 代码块6:遍历table[index]所连接的链表,查找是否已经存在key与需要插入的key值相同的节点,如果存在则直接更新value,并返回旧的value。
  • 代码块7:如果table[index]所连接的链表上不存在相同的key,则通过addEntry()方法将新节点加载链表的开头

jdk1.8中hashtable源码分析
说明:

  • 代码块1:如果加入新节点后,hashtable中元素的个数超过了阈值threshold,则利用rehash()对数组进行扩容。
  • 代码块2:e=table[index],并将新节点加在了e节点的1前面,最后table[index]=e。相当于把把新节点放在table[index]位置,即整个链表的首部
    Hashtable中数组的扩容:
    jdk1.8中hashtable源码分析
    即:每次扩容时,容量都变成了原来的2倍。

Hashtable的get操作实现

jdk1.8中hashtable源码分析
说明:

  • 代码块1:hashtable之所以是线程安全的,原因为在put和get方法上使用synchronized关键字进行修饰。
  • 代码块2:进行hash值的寻址,找到在table数组中的位置index.
  • 代码块3:遍历table[index]链表,找到key值相同的节点的value返回,注意同样在该过程中使用到了key的equal方法,所以key被应用与hashtable时不仅要实现hashcode方法还有实现equal方法

Hashtable和hashmap的区别总结

1、 hashmap中key和value均可以为null,但是hashtable中key和value均不能为null。

2、 hashmap采用的是数组(桶位)+链表+红黑树结构实现,而hashtable中采用的是数组(桶位)+链表实现。

3、 hashmap中出现hash冲突时,如果链表节点数小于8时是将新元素加入到链表的末尾,而hashtable中出现hash冲突时采用的是将新元素加入到链表的开头。

4、 hashmap中数组容量的大小要求是2的n次方,如果初始化时不符合要求会进行调整,而hashtable中数组容量的大小可以为任意正整数。

5、 hashmap中的寻址方法采用的是位运算按位与,而hashtable中寻址方式采用的是求余数。

6、 hashmap不是线程安全的,而hashtable是线程安全的,hashtable中的get和put方法均采用了synchronized关键字进行了方法同步。

7、 hashmap中默认容量的大小是16,而hashtable中默认数组容量是11。

相关文章: