Java HashMap、Hashtable、HashSet、TreeMap 之间的区别
·
一、HashMap 和 Hashtable 的区别
- 线程是否安全:HashMap 是非线程安全的,Hashtable 是线程安全的,因为 Hashtable 内部的方法基本都经过 synchronized 修饰;
- 效率:因为线程安全的问题,HashMap 要比 Hashtable 效率高一点。另外,Hashtable 基本被淘汰,不在代码中使用;
- 对 Null key 和 Null value 的支持:HashMap 可以存储 null 的 key 和 value,但 null 作为 key 只能有一个,null 作为值可以有多个;Hashtable 不允许有 null key 和 null value,否则会抛出 NullPointerException;
- 初始容量大小和每次扩容大小:
1、创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11 ,之后每次扩容,容量变为原来的 2n+1;
2、HashMap 默认的初始化大小为 16,之后每次扩容,容量变为原来的 2 倍;
3、创建时如果给定了容量初始值,那么 Hashtable 会直接使用给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小;
- 底层数据结构:两者底层数据结构都是数组+链表,但是 JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间。Hashtable 没有这样的机制。
- 哈希函数的实现:HashMap 对哈希值进行了高位和低位的混合扰动处理以减少冲突,而 Hashtable 直接使用键的 hashCode() 值。
二、HashMap 和 HashSet 的区别
HashSet 底层是基于 HashMap 实现的,除了 clone()、writeObject()、readObject()是 HashSet 自己实现的,其他方法都是直接调用 HashMap 中的方法。
| HashMap | HashSet |
| 实现了 Map 接口 | 实现 Set 接口 |
| 存储键值对 | 仅存储对象 |
| 调用 put() 向 map 中添加元素 | 调用 add() 方法向 Set 中添加元素 |
| HashMap 使用 key 计算 hashcode |
HashSet 使用成员对象来计算 hashcode 值,对于两个对象来说 hashcode 可能相同,所以 equals() 方法用来判断对象的相等性 |
三、HashMap 和 TreeMap 的区别
TreeMap 和 HashMap 都继承自 AbstractMap,TreeMap基于红黑树实现 ,但是需要注意的是 TreeMap 它还实现了 NavigableMap 接口和 SortedMap 接口。实现 NavigableMap 接口让 TreeMap 有了对集合内元素的搜索能力。
NavigableMap 接口提供了丰富的方法来探索和操作键值对:
- 定性搜索:ceilingEntry(), floorEntry(), higherEntry() 和 lowerEntry() 等方法可以用于定位大于等于、小于等于、严格大于、严格小于给定键的最接近的键值对;
- 子集操作:subMap(), headMap() 和 tailMap() 方法可以高效地创建原集合的子集视图,而无需复制整个集合;
- 逆序视图:descendingMap() 方法返回一个逆序的 NavigableMap 视图,使得可以反向迭代整个 TreeMap;
- 边界操作:firstEntry(), lastEntry(), pollFirstEntry()和 pollLastEntry() 等方法可以方便地访问和移除元素;
这些方法都是基于红黑树数据结构的属性实现的,红黑树保持平衡状态,从而保证了搜索操作的时间复杂度为 O(log n),这让 TreeMap 成为了处理有序集合搜索问题的强大工具。
综上所述,相比于 HashMap,TreeMap 主要多了对集合中的元素根据键排序的能力以及对集合内元素的搜索能力。
更多推荐


所有评论(0)