缘由
听到前面now直播的大哥在面试同学,问了对面同学一个问题:请问Hashtable
是用什么实现的?然后我就一脸愣逼,我记得《stl源码剖析》中好像没有讲到Hashtable
,只说了map
,set
,mutimap
,mutiset
,所以哈希是什么东西?黑人问号。我能说出set
就是map
的阉割版本,底层结构是红黑树,红黑树的定义,旋转以及为何要用红黑树,但是Hashtable
确实不甚了解啊。唯一知道的就是经常拿它去和HashMap
比较,什么线程安全啦,key
,value
都不能为null
什么的。所以我就开始阅读源码,看看有什么区别?
实现的区别
Hashtable
继承Dictionary
类,可序列化,可以拷贝(实现了Serializable
,Cloneable
);与之相对HashMap
多实现了Map
和改为继承AbstractMap
了。
Hashtable
将元素存储在一个Entry[]
数组,HashMap
将元素存储在一个Node[]
中。注意Entry
,Node
都有一个关键属性next
,为了以后hashcode
冲突后进行头部插入元素用的。所以这两者都采用了链表的方法来解决冲突问题。
对于put
方法,两者的最大区别在于hashcode
的区别。Hashtable
直接使用对象类定义的hashcode
方法;而HashMap
则是用了自定义的hashcode
,区别就是如下代码:
private int hashcode(Object o){
return o -- null? 0 : o.hashcoe();
}
从设计模式的角度看,就是加了一个中间间,一个桥接方法,导致了即使key
或者value
为null
的时候也可以哈希,而不是跑出一个NPE
。
对于forEach
方法。两者都差不多:两层for
循环,第一层便利slot
(槽区),第二个遍历单链。
对于get
方法:HashMap
多了一步——检查空值,而且HashMap
中一般对于Node
读取都要考虑null
(比如contain
,remove
)。
至于为什么Hashtable
是线程安全的,是因为它的方法加上了synchronic
,所以线程安全。
还有就是HashMap
内涵entrySet
;冲突时链表添加节点的方法不一样,Hashtable
是调用一个函数addEntry
,而HashMap
是用p.next = new Node(key, value)
的。
总而言之,它们的区别就在于synchronic
和 hashcode
,以及内部维护的数据规模不一样。
网友评论