HashMap和HashTable
HashMap
和 Hashtable
都实现了 Map 接口,都是 Java 中用于存储键值对的数据结构,它们的底层数据结构都是数组加链表的形式(默认情况下),但它们存在以下几点不同:
- 线程安全:
HashTable
是线程安全的,而 HashMap 是非线程安全的。 - 性能:因为
HashTable
使用了synchronized
给整个方法添加了锁,所以相比于HashMap
来说,它的性能不如HashMap
。 - 存储:
HashMap
允许 key 和 value 为 null,而 HashTable不允许存储 null 键和 null 值。
HashTable
不允许存储null键值的原因是:
- 基于
Dictionary
类:HashTable
类继承自Dictionary
类,而Dictionary
类在处理键和值时,不允许null
作为键或值。这是HashTable
不能存储null
键和值的直接原因。 - 在
HashTable
的get
、put
和remove
等方法中,如果传入null
作为键或值,会抛出NullPointerException
。
pubtic synchronized V put(K key, V value) {// Make sure the value is not nuL1if (value == nuLl) {throw new NullPointerException();}
}
而HashMap
允许 key 和 value 为 null 的原因是因为在 HashMap
中对 null 值进行了特殊处理,如果为 null 时会把它赋值为 0
static final int hash(0bject key) {int h;return (key == null) ? 0= key. hashCode()) /^(h>>>16);
}
虽然HashTable
是线程安全的,但在多线程环境下官方也不推荐使用 HashTable
,因为 HashTable
是给整个方法添加 synchronized
来实现线程安全的,所以它的性能很差。官方推荐在多线程环境下,使用线程安全的 ConcurrentHashMap
来完成数据存储。
HashMap 和 HashSet
HashSet
实现了 Set 接口,只存储对象;HashMap
实现了 Map 接口,用于存储键值对。
HashSet
的实现和特性
- Set接口实现:
HashSet
实现了Set
接口,这意味着它是一个不允许重复元素的集合。Set
接口定义了集合的基本操作,如添加、删除和检查元素是否存在。
- 存储对象:
HashSet
只存储对象,这些对象可以是任何类型的,包括自定义对象。但是,为了正确地比较对象是否相等,存储在HashSet
中的对象必须正确地实现equals()
和hashCode()
方法。
- 底层实现:
HashSet
的底层实现确实是基于HashMap
。每个HashSet
元素都作为HashMap
的键存储,而HashMap
的值则固定为PRESENT
(一个静态的布尔值)。
- 不允许重复:
- 由于
HashMap
的键不允许重复,因此HashSet
也不允许有重复的元素。如果尝试添加一个已经存在的元素,HashSet
会忽略这个操作,不会插入重复的元素。
- 由于
- 性能:
HashSet
提供了高效的查找、插入和删除操作,平均时间复杂度为 O(1)。这是因为它依赖于HashMap
的快速查找特性。
HashSet 适用于只存储对象的情况,而 HashMap 适用于需要存储键值对的情况,可以根据键快速查找值。HashSet 底层是用 HashMap 存储的,用它可以存储不重复的值。