Map集合框架
- 1、Map集合框架
-
- [1.1 关于Map接口中的主要实现类](#1.1 关于Map接口中的主要实现类)
- [1.2 各实现类的特点:](#1.2 各实现类的特点:)
- [2. HashMap 和 Hashtable 的区别](#2. HashMap 和 Hashtable 的区别)
- [3. HashMap 和 HashSet 区别](#3. HashMap 和 HashSet 区别)
- [4. HashMap 和 TreeMap 区别](#4. HashMap 和 TreeMap 区别)
1、Map集合框架
注意:Map接口是在java.util.Map
的包下,Map
接口不是 Collection
的子接口,它是使用键、值映射表来存储【Map 不能有重复的键(覆盖),每个键可以映射到最多一个值】。
Map 接口的实现类较多,在此我们关注 HashMap 、 TreeMap 、 HashTable 、 LinkedHashMap
1.1 关于Map接口中的主要实现类
- 继承结构图如下所示
- Map接口实现类的代码:
- HashMap类:
java
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
- TreeMap类:
java
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
- LinkedHashMap类:
java
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
- Hashtable类:
java
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable
1.2 各实现类的特点:
- HashMap
- 基于哈希表的实现的 Map 接口
- 允许 null 的值和 null 键
- 非线程安全
- 默认容量 16,默认负载因子 0.75
- HashMap容量为什么是2的n次方
- 扩容是 2 倍旧的容量
- 在存储数据时,
key
的hash
计算调用的是 HashMap 中的hash
方法 - 添加value 值 时,如果
hash
一样添加到链表尾部 - 关于HashMap中添加元素的过程【put的过程】详细介绍点击这里
- TreeMap
- 继承 AbstractMap ,底层数据结构是一个红黑树基于 NavigableMap 实现
- 非线程安全的
- key 不能存
null
,但是 value 可以存null
- key 必须是可比较的 (即要么实现 Comparable 接口,要么传递一个 Comparator 比较器)
- Hashtable
- 该类实现了一个哈希表,它将键映射到值
- 不允许
null
作为键和值 - 默认初始容量(
initialCapacity
)为11
,默认负载因子(loadFactor
)为0.75f
- 同步的(线程安全的)
- 不保证顺序
- 扩容方式是旧容量的2倍 +1
- 为什么hashtable的扩容方式选择为2n+1,可点击这里查看
- 为了均匀分布,降低冲突率
- 数组 + 链表方式存储
- 添加值时
- 如果 hash 一样 equals 为 false 则将当前值添加到链表头
- 如果 hash 一样 equals 为 true 则使用当前值替换原来的值 ( key 相同)。
- LinkedHashMap
- 哈希表和双向链表实现的 Map 接口
- 具有可预测的迭代次序(有序)
- 非线程安全
- 允许空元素
2. HashMap 和 Hashtable 的区别
- 线程是否安全: HashMap 是非线程安全的, Hashtable 是线程安全的,因为Hashtable 内部的方法基本都经过
synchronized
修饰。(如果你要保证线程安全的话就使用ConcurrentHashMap
吧!,Hashtable已经过时了); - 效率: 因为线程安全的问题, HashMap 要比 Hashtable 效率高一点。
- 对
Null key
和Null value
的支持: HashMap 可以存储null
的key
和value
,但 null 作为键只能有一个,null 作为值可以有多个;Hashtable 不允许有null
键和null
值,否则会抛出 NullPointerException 。 - 初始容量大小和每次扩充容量大小的不同:
- 创建时如果不指定容量初始值, Hashtable 默认 的初始大小为
11
,之后每次扩充,容量变为原来的2n+1
。 - HashMap 默认 的初始化大小为
16
。之后每次扩充,容量变为原来的2 倍
。 - 创建时如果给定 了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小。
- 创建时如果不指定容量初始值, Hashtable 默认 的初始大小为
- 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突 时有了较大的变化,当链表长度大于阈值 (默认为 8)时,将链表转化为红黑树 (将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间。 Hashtable 没有这样的机制。
3. HashMap 和 HashSet 区别
- HashSet 底层就是基于 HashMap 实现的。
- 实现接口不同
- HashMap 实现
Map接口
- HashSet 实现
Set接口
- HashMap 实现
- 存储不同
- HashMap 存储
键值对
- HashSet 存储
对象
- HashMap 存储
- 添加方式不同
- HashMap 调用
put()
添加元素 - HashSet 调用
add()
添加元素
- HashMap 调用
- 计算HashCode不同
- HashMap 使用键(Key)计算
hashcode
- HashSet 使用成员对象来计算
hashcode
值,对于两个不同的对象来说hashcode
可能相同,所以还要用equals()
方法用来判断对象的相等性.
- HashMap 使用键(Key)计算
4. HashMap 和 TreeMap 区别
- TreeMap 和 HashMap 都继承自
AbstractMap
,但是需要注意的是 TreeMap 它还实现了 NavigableMap 接口和 SortedMap 接口。 - 实现
NavigableMap
接口让TreeMap
有了对集合内元素的搜索的能力。 - 实现
SortedMap
接口让TreeMap
有了对集合中的元素根据键排序的能力。
综上,相比于HashMap
来说 TreeMap
主要多了对集合中的元素根据键排序的能力以及对集合内元素的搜索的能力。