Contents

hashmap和hashtable之间的差异

1. 概述

在这个简短的教程中,我们将重点关注 *Hashtable *和 *HashMap *之间的核心区别。

2. Java中的HashtableHashMap

HashtableHashMap 非常相似——都是实现 Map接口的集合。

此外,  put()get()、*remove()*和 containsKey() 方法提供恒定时间性能 O(1)。在内部,这些方法基于使用桶存储数据的散列的一般概念工作。

两个类都没有维护元素的插入顺序。换句话说,当我们迭代这些值时,添加的第一个项目可能不是第一个项目。

但它们也有一些差异,在某些情况下,它们会比另一种更好。让我们仔细看看这些差异。

3. HashtableHashMap的区别

3.1. 同步

首先,Hashtable是线程安全的,可以在应用程序中的多个线程之间共享。

另一方面,HashMap是不同步的,如果没有额外的同步代码,是不能被多个线程访问的。我们可以使用 Collections.synchronizedMap()来制作HashMap的线程安全版本。我们也可以只创建自定义锁代码或使用synchronized关键字使代码线程安全。

HashMap不同步,因此它比Hashtable更快并且使用更少的内存。通常,在单线程应用程序中,非同步对象比同步对象快。

3.2. 空值

另一个区别是null处理。HashMap允许添加一个 以null为键的条目以及多个以null为值的条目。相反,Hashtable根本不允许null**。让我们看一个nullHashMap的例子:

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具有相同的EnumeratorIteratorEnumerator的继承者,消除了它的一些缺点。例如,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