Java集合大总结——Map集合

本文详细介绍了Java中的Map接口及其主要实现类HashMap、Hashtable、TreeMap和LinkedHashMap,比较了它们的线程安全、效率、null键值支持、初始容量和底层数据结构特点。

1、Map集合框架

注意:Map接口是在java.util.Map 的包下,Map 接口不是 Collection 的子接口,它是使用键、值映射表来存储【Map 不能有重复的键(覆盖),每个键可以映射到最多一个值】。
Map 接口的实现类较多,在此我们关注 HashMap 、 TreeMap 、 HashTable 、 LinkedHashMap

1.1 关于Map接口中的主要实现类

  1. 继承结构图如下所示
    在这里插入图片描述
  2. Map接口实现类的代码:
  • HashMap类:
public class HashMap<K,V> extends AbstractMap<K,V>
   implements Map<K,V>, Cloneable, Serializable 
  • TreeMap类:
public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
  • LinkedHashMap类:
public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
  • Hashtable类:
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable

1.2 各实现类的特点:

  • HashMap
  • TreeMap
    • 继承 AbstractMap ,底层数据结构是一个红黑树基于 NavigableMap 实现
    • 非线程安全的
    • key 不能存 null ,但是 value 可以存 null
    • key 必须是可比较的 (即要么实现 Comparable 接口,要么传递一个 Comparator 比较器)
  • Hashtable
    • 该类实现了一个哈希表,它将键映射到值
    • 不允许 null 作为键和值
    • 默认初始容量(initialCapacity)为 11 ,默认负载因子( loadFactor )为 0.75f
    • 同步的(线程安全的)
    • 不保证顺序
    • 扩容方式是旧容量的2倍 +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 可以存储 nullkeyvalue,但 null 作为键只能有一个,null 作为值可以有多个;Hashtable 不允许有null键和null值,否则会抛出 NullPointerException 。
  • 初始容量大小和每次扩充容量大小的不同:
    • 创建时如果不指定容量初始值, Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的 2n+1
    • HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍
    • 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小
  • 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间。 Hashtable 没有这样的机制。

3. HashMap 和 HashSet 区别

  • HashSet 底层就是基于 HashMap 实现的。
  • 实现接口不同
    • HashMap 实现Map接口
    • HashSet 实现Set接口
  • 存储不同
    • HashMap 存储键值对
    • HashSet 存储对象
  • 添加方式不同
    • HashMap 调用put()添加元素
    • HashSet 调用add()添加元素
  • 计算HashCode不同
    • HashMap 使用键(Key)计算 hashcode
    • HashSet 使用成员对象来计算hashcode值,对于两个不同的对象来说hashcode 可能相同,所以还要用 equals() 方法用来判断对象的相等性.

4. HashMap 和 TreeMap 区别

  1. TreeMap 和 HashMap 都继承自 AbstractMap ,但是需要注意的是 TreeMap 它还实现了 NavigableMap 接口和 SortedMap 接口。
  2. 实现NavigableMap接口让 TreeMap 有了对集合内元素的搜索的能力。
  3. 实现SortedMap接口让 TreeMap 有了对集合中的元素根据键排序的能力。

综上,相比于HashMap来说 TreeMap 主要多了对集合中的元素根据键排序的能力以及对集合内元素的搜索的能力。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-今非昔比°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值