首先这个问题是面试中很常见的问题,但一般的面试者只能回答出两三点,而且这两个在平时开发中也很常用。
1.线程安全
HashTable 是线程安全的,HashMap不是。观察一下HashTable的put的方法的源码和HashMap的put的方法的源码就知道了:
public synchronized V put(K key, V value) {
...
}
public V put(K key, V value) {
...
}
HashTable的所有元素的操作都是有synchronized修饰的
2.性能优劣
既然HashTable是线程安全的,每个方法都要阻塞其他线程,所以性能方面肯定是比较差了,HashMap性能更好,所以使用更广,如果既要保证线程安全又要保证性能,最好使用JUC包下的ConcurrenceHashMap
3.NULL 值
HashTable是不允许key或者value为NULL的,而HashMap则可以。看源码:
分析一下HashTable的put的方法:
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 = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
...
如果key为null的话直接抛出空指针,HashMap的put的方法:
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
...
对null值做了处理。
扫描二维码关注公众号,回复:
4992305 查看本文章
4.实现方式
HashTable的实现方式:
HashMap的实现方式:
两者继承的父类不同。
5.容量扩充
HashTable的无参构造:
HashMap的无参构造:
当现有容量大于总容量*负载因子时,HashTable的扩容规则是当前容量翻倍+1;HashMap的扩容规则是当前容量翻倍;
6.迭代器
//csdn博客---HopeLee
Hashtable<String,String> ht = new Hashtable();
ht.put("t1","2");
ht.put("t2","3");
ht.put("t3","4");
Enumeration<Map.Entry<String, String>> iterator =(Enumeration<Map.Entry<String, String>>) ht.entrySet().iterator();
ht.remove(iterator.nextElement().getKey());
while(iterator.hasMoreElements())
{
System.out.println(iterator.nextElement());
}
System.out.println("====================");
HashMap<String,String> hm =new HashMap<>();
hm.put("h1","2");
hm.put("h2","3");
hm.put("h3","4");
Iterator<Map.Entry<String, String>> iterator2 = hm.entrySet().iterator();
hm.remove(iterator2.next().getKey());
while(iterator2.hasNext())
{
System.out.println(iterator2.next());
}
输出的结果是:
t2=3
t1=2
====================
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
at java.util.HashMap$EntryIterator.next(HashMap.java:962)
at java.util.HashMap$EntryIterator.next(HashMap.java:960)
at com.lff.nov.DatabaseTest.main(DatabaseTest.java:64)
HashMap的迭代器Iterator是fail-fast的,而HashTable的迭代器Enumeration不是,所以当其他线程有改变HashMap的结构时,如删除、增加元素,就会抛出java.util.ConcurrentModificationException。