hashmap和hashtable之间的差异
1. 概述
在这个简短的教程中,我们将重点关注 *Hashtable *和 *HashMap *之间的核心区别。
2. Java中的Hashtable和HashMap
Hashtable和HashMap 非常相似——都是实现 Map接口的集合。
此外, put()、get()、*remove()*和 containsKey() 方法提供恒定时间性能 O(1)。在内部,这些方法基于使用桶存储数据的散列的一般概念工作。
两个类都没有维护元素的插入顺序。换句话说,当我们迭代这些值时,添加的第一个项目可能不是第一个项目。
但它们也有一些差异,在某些情况下,它们会比另一种更好。让我们仔细看看这些差异。
3. Hashtable和HashMap的区别
3.1. 同步
首先,Hashtable是线程安全的,可以在应用程序中的多个线程之间共享。
另一方面,HashMap是不同步的,如果没有额外的同步代码,是不能被多个线程访问的。我们可以使用 Collections.synchronizedMap()来制作HashMap的线程安全版本。我们也可以只创建自定义锁代码或使用synchronized关键字使代码线程安全。
HashMap不同步,因此它比Hashtable更快并且使用更少的内存。通常,在单线程应用程序中,非同步对象比同步对象快。
3.2. 空值
另一个区别是null处理。HashMap允许添加一个 以null为键的条目以及多个以null为值的条目。相反,Hashtable根本不允许null**。让我们看一个null和HashMap的例子:
HashMap<String, String> map = new HashMap<String, String>();
map.put(null, "value");
map.put("key1", null);
map.put("key2", null);
这将导致:
assertEquals(3, map.size());
接下来,让我们看看 Hashtable 有什么不同:
Hashtable<String, String> table = new Hashtable<String, String>();
table.put("key", null);
这会导致NullPointerException。添加以null作为键的对象也会导致NullPointerException:
table.put(null, "value");
3.3. 元素迭代
HashMap使用 Iterator 来迭代值,而 Hashtable具有相同的Enumerator。Iterator是Enumerator的继承者,消除了它的一些缺点。例如,Iterator有一个*remove()*方法来从底层集合中删除元素。
Iterator 是一个快速失败 的迭代器。换句话说, 当底层集合在迭代时被修改时,它会抛出一个ConcurrentModificationException 。让我们看一下快速失败的例子:
HashMap<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()){
iterator.next();
map.put("key4", "value4");
}
这会引发ConcurrentModificationException异常,因为我们在迭代集合时调用了put()。
4. 何时选择HashMap而不是Hashtable
我们应该将 HashMap 用于非同步或单线程应用程序。
值得一提的是,从 JDK 1.8 开始, Hashtable 已被弃用。但是,ConcurrentHashMap 是一个很好的Hashtable 替代品。我们应该考虑 在具有多个线程的应用程序中使用ConcurrentHashMap。