Hashtable和HashMap类之间存在多个显著的不同点。它们的历史背景不同。Hashtable是基于古老的Dictionary类,而HashMap则是Java 1.2版本中Map接口的一个创新实现。
最关键的区别在于Hashtable的方法是同步的,而HashMap的方法则不是。这意味着在多线程环境中,使用Hashtable无需额外同步措施,但HashMap则需要外部同步。一种便捷的方法是使用Collections类的静态synchronizedMap方法,它创建一个线程安全的Map对象。这样做虽然提供了同步访问,但在不需要同步的单线程应用中却无法关闭Hashtable的同步,且同步增加了额外的处理开销。
第三点不同在于,HashMap允许使用空值作为表的条目key或value,而Hashtable则不允许。在HashMap中,只有一条记录可以拥有空的key,但任意数量的条目可以拥有空的value。当未找到搜索键或找到搜索键但值为空时,get()方法都会返回null。需要使用containKey()方法来区分这两种情况。
关于选择使用Hashtable还是HashMap,一般建议在需要同步时使用Hashtable,反之使用HashMap。考虑到HashMap可以在需要时进行同步,并且拥有更多功能而非基于陈旧类,有人认为HashMap在多数情况下优于Hashtable。
有时你可能会想用Hashtable来映射key的字符串到value的字符串,例如环境字符串中的key和value映射。虽然Hashtable是实现这一功能的一种方法,但Java还提供了另一种方法——Java.util.Properties类。Properties类是Hashtable的一个子类,专为处理String类型的keys和values而设计。其用法与Hashtable相似,但增加了两个省时的方法:Store()和Load(),分别用于将Properties对象内容保存至文件和从文件读取内容。
值得注意的是,Properties类扩展了Hashtable类,因此可以使用超类的put()方法来添加非String对象的keys和values,但这是不推荐的。若使用store()方法针对不包含String对象的Properties对象,将会失败。取而代之的是setProperty()和getProperty()方法,它们使用String参数。
至于两者的主要区别,Hashtable是线程安全的,而HashMap则不是。在细节实现上,Hashtable通过添加synchronized关键字到其实现方法上来确保线程同步,因此相对来说HashMap的性能会更高一些。在无需特殊需求的情况下,建议使用HashMap。而在多线程环境下使用HashMap时,需要使用collections.synchronizedMap()方法来获取一个线程安全的集合。HashMap允许使用null作为key(但建议避免这样做),而Hashtable则不允许使用null作为key。最后Hashtable和HashMap的初始容量、扩容策略、底层数据结构实现等方面也存在差异。总的来说二者设计原理基本相同。但在并发场景下考虑性能与线程安全性的平衡时可以选择ConcurrentHashMap等更高级别的并发集合类来实现数据存储和访问的并发控制。ConcurrentHashMap提供了一种独特的锁机制,与传统的Hashtable和SynchronizedMap不同。Hashtable所采取的锁机制是全局锁定,即对整个hash表进行锁定,因此只能有一个线程在任何时刻对其进行操作。而ConcurrentHashMap则采用了分段锁技术,每次只锁定一个桶。
在竞争激烈的多线程环境下,Hashtable的锁定机制表现出效率较低的缺陷。其原因在于,所有访问Hashtable的线程都需要竞争同一把锁。为了解决这个问题,ConcurrentHashMap采用了锁分段技术。它将数据分成多个段,并为每个段分配一把锁。这样,当多个线程访问不同数据段时,它们之间就不会存在锁的竞争。可以显著提高并发访问的效率。
具体来说,ConcurrentHashMap首先会将数据分成多个段进行存储。然后,当一个线程占用某一段数据的锁时,其他线程仍然可以访问其他的数据段。这种设计不仅保证了线程安全,还提高了并发性能。通过这种锁分段技术,ConcurrentHashMap能够在多线程环境下实现高效的并发访问。