- Java中HashMap和HashTable有什么区别
线程安全性:
HashMap:非线程安全。在多线程环境下,如果没有采取适当的同步措施,直接并发访问可能会导致数据不一致、死锁等问题。如果需要在多线程环境中安全地使用HashMap,通常需要外部加锁(如使用synchronized关键字、Lock对象或ConcurrentHashMap等)。
HashTable:线程安全。它的所有公开方法都使用了synchronized关键字进行同步,确保在多线程环境下对HashTable的操作是线程安全的。但这也意味着在并发访问时会有较高的同步开销,可能影响性能。
允许null值:
HashMap:允许键(key)和值(value)为null。但是要注意,一个HashMap中最多只能有一个null键,且可以有任意数量的null值。
HashTable:不允许键或值为null。试图将null键或null值放入HashTable会抛出NullPointerException。
父类与实现细节:
HashMap:继承自AbstractMap类,它使用数组+链表(或红黑树,当链表长度超过阈值时)的结构来存储数据,通过散列函数和扩容机制来保证高效查找。HashMap在JDK 1.8之后引入了红黑树优化,当链表长度超过阈值时会转为红黑树,进一步提高查找效率。
HashTable:继承自古老的Dictionary类,同样使用散列桶+链表的结构存储数据。Dictionary类现在已经很少被直接使用,且HashTable未采用红黑树优化。
性能:
HashMap:由于是非线程安全的,所以在单线程环境下性能较好,没有不必要的同步开销。
HashTable:由于内部方法同步,所以在多线程访问时能保证数据一致性,但付出的代价是降低了并发性能。在单线程环境下,其性能通常不如HashMap。
其他区别:
迭代器:HashMap的迭代器在迭代过程中如果修改了映射关系(比如调用remove()方法移除元素),会抛出ConcurrentModificationException。若需在迭代过程中修改映射,可以使用Iterator.remove()方法。而HashTable的迭代器在迭代过程中即使修改了映射关系也不会抛出异常。
如果大家需要视频版本的讲解,欢迎关注我的B站: