`

简单比较HashMap和Hashtable

阅读更多
Hashtable作为遗留类,其实完全可以弃置不用了。从这个角度来看,似乎本文的实际意义不大。写本文,其实大有自娱自乐之意,另外给自己备忘,呵呵~
本站也有很多这类的文章了,我做的工作只不过是收集并分析这些文章,然后给出一个容易理解的综合帖罢了。
本文主要阐述了HashMap和Hahstable下面几点不同:
  • 1、线程安全
  • 2、key/value是否可为null
  • 3、求hash码以及index的机制不同
  • 4、contains/containsValue/containsKey方法
  • 5、迭代器



1、线程安全
看源码,很容易发现Hashtable是线程安全的,而HashMap不是。而Hashtable实现线程安全的机制是给所有需要同步处理的方法加上synchronized关键字。
如果要让HashMap变成线程安全的,除了自己实现或者用JDK里自带的线程安全类之外,我们可以用java.util.Collections提供的synchronizedMap方法获得一个进行同步处理封装后的Map。

2、key/value是否可为null
HashMap允许在table[0]位置保存一对key为null的k-v,并且从来不对value是否为null进行验证。
而Hashtable所有的key和value都不能为空,否则报出空指针异常。

3、求hash码以及index的机制不同
Hashtable中put一个新k-v对的时候,调用这个方法:
public synchronized V put(K key, V value) {
	// Make sure the value is not null
	if (value == null) {
	    throw new NullPointerException();
	}

	// Makes sure the key is not already in the hashtable.
	Entry tab[] = table;
	int hash = key.hashCode();
	int index = (hash & 0x7FFFFFFF) % tab.length;
	for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
	    if ((e.hash == hash) && e.key.equals(key)) {
		V old = e.value;
		e.value = value;
		return old;
	    }
	}

其中int index = (hash & 0x7FFFFFFF) % tab.length;可以看出,不像HashMap中复杂的hash()方法,这里只是简单的通过hash & 0x7FFFFFFF将hash值变为正数,然后用求余方式求得index相对于HashMap位运算。在HashMap调用put方法判断key是否重复的方式是e.hash == hash && ((k = e.key) == key || key.equals(k)),而在HashTable中是(e.hash == hash) && e.key.equals(key)。为了方便位运算求index,HashMap中的table初始容量是16,然后每次扩容都是*2,而在Hashtable默认初始容量为15,扩容的时候int newCapacity =oldCapacity * 2 + 1;两者的默认加载因子都是0.75.
由于两者使用的算法差不多,所以一般情况下两者的性能相差不大。

4、contains/containsValue/containsKey方法
Hashtable中:
contains传入的参数是value,containsValue方法和contains同样的作用,因为它内部就是调用contains来处理的。containsKey在判断到(e.hash == hash) && e.key.equals(key)为true的时候就会返回ture。

HashMap中:
没有容易混淆意义的contains方法。containsValue方法会分value是否为null(因为HashMap对value是否为null不做要求)进行判断,两者都是遍历然后判断value.equals(e.value)(传入的value参数不为null)或者e.value == null(传入的value参数为null)是否为true,如果为true则该方法返回true。containsKey判断标准是e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))是否为true。

5、迭代器
HashTable使用Enumeration,HashMap使用Iterator 。
实际上,这是一个历史原因,在jdk1.0和jdk1.1版本中,jdk的设计者选择了Enumeration作为迭代器,在设计jdk1.2他们也许是因为Enumeration中的方法名字太长了,也许是因为Iterator 这个名字更加符合迭代器的本质,所以就改为了Iterator 。其实Iterator 比Enumeration多出的只是一个remove方法,其他完全一样。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics