HashMap 和 Hashtable 都是 Java 中用于存储键值对的数据结构,它们都实现了 Map 接口,但存在以下几个主要区别:

  1. 线程安全性
  • HashTable 是线程安全的,其方法都是同步的(即在多线程环境下使用时会自动进行内部加锁),因此多个线程可以安全地同时读写 HashTable,但可能会牺牲一定的性能。
  • HashMap 在设计上并没有考虑线程安全问题,因此在多线程环境下如果不采取适当的同步控制措施,直接并发访问可能会导致数据不一致或出现意外的行为。
  1. null 值处理
  • HashTable 不允许插入 null 键和 null 值,试图插入 null 会抛出 NullPointerException
  • HashMap 允许插入 null 键和 null 值,但是只有一个 null 键和任意数量的 null 值。
  1. 效率
  • 因为不需要进行线程同步,所以单线程环境下 HashMap 的操作通常比 HashTable 更快。
  1. 迭代器行为
  • 当一个 HashMap 或 HashTable 在迭代过程中被修改(如添加、删除元素)时,HashtableIterator 会抛出 ConcurrentModificationException 异常。
  • 虽然 HashMap 在某些版本的 Java 也会抛出此异常,但在 Java 5 及以后引入了 ConcurrentHashMap 类,并且对 HashMap 进行了改进,提供了 fail-fast(快速失败)迭代器机制,这意味着如果在迭代期间结构发生变化,则迭代器会立即抛出异常。
  1. 哈希算法
  • 虽然具体的实现细节可能随 Java 版本有所变化,但两者都会根据键的哈希码来计算存储位置。关于哈希值的计算方式,早期版本中可能有所不同,不过在现代 Java 版本中,两者的哈希策略和冲突解决方法已经很相似。
  1. 历史及现代实践
  • Hashtable 是较早出现在 Java 中的类,在集合框架的发展过程中,由于线程安全方面的限制以及性能因素,逐渐被非线程安全但性能更高的 HashMap 取代,尤其是在单线程应用或者需要线程安全但又追求高性能的场景下,会选择使用 ConcurrentHashMap 替代 HashTable