Map接口

本文详细介绍了Java中Map接口的两个重要实现类HashMap和TreeMap。HashMap内部采用数组+链表+红黑树的数据结构,通过哈希函数定位元素,支持快速插入、删除和查找。当链表长度超过8且数组长度大于64时,链表会转换为红黑树以提高性能。HashMap是非线程安全的,而HashTable则是线程安全但效率较低。LinkedHashMap是HashMap的子类,提供插入或访问顺序的迭代。TreeMap基于红黑树,要求Key实现Comparable接口,提供有序的Key遍历。
摘要由CSDN通过智能技术生成

目录

一、Map

二、实现类一:HashMap

一、底层实现

二、HashMap的扩容

三、与HashTable的区别

四、LinkedHashMap

 三、实现类二:TreeMap


一、Map

Map是一种键值对集合,Map集合中的每一个元素都包含一个键对象和一个值对象。其中,键对象不允许重复,而值对象可以重复,并且值对象还可以是Map类型的,就像数组中的元素还可以是数组一样。

二、实现类一:HashMap

一、底层实现

Map<K,V>是一种键-值映射表,当我们调用put(K key,V value)方法时,就把key和value做了映射并放入Map。当我们调用V get(K key)时,就可以通过key获取到对应的value。如果key不存在,则返回null。和list类似,Map也是一个接口,最常用的实现类就是HashMap。

HashMap内部数据结构使用数组+链表+红黑树进行存储。数组类型为Node[],每个Node都保存了某个键值对元素的key、value、hash、next等值。由于next的存在,所以每个Node对象都是一个单项链表中的组成节点。

当新添加一个KV键值对元素时,通过该元素的key的hash值,计算该元素在数组中应该保存的位置。如果该下标位置如果已经存在其他Node对象(产生hash冲突),则采用连地址法处理,即将新添加的KV键值对元素将以链表形式存储。将新元素封装成一个新的Node对象,插入到该下标位置的链表尾部。当链表的长度超过8并且数组长度大于64时,为了避免查找搜索性能下降,该链表会转换成一个红黑树。

二、HashMap的扩容

HashMap初始化时,默认的数组大小只有16,通过位运算1<<4计算得出。并且,数组的长度必须为2的幂次方。因为数组长度为2的幂次方,同时可以使用&运算,结合hash值,快速计算该元素在数组中的下标位置,提高HashMap的使用效率。

扩容过程中是需要按照数组容量和加载因子来进行判断的。

数组容量:基础数组Node<K,V>[] table 的长度。如果没有指定容量,添加第一个元素时,该数组按照默认值16进行初始化。

加载因子:用来表示HashMap集合中的元素的填满程度,默认为0.75f。越大则表示可以填充的元素越多,集合的空间利用率越高,但是冲突的机会就会增大。

 扩容有两种情况:

  1. HasnMap中的元素超过扩容阈值threshold时,就会进行数组扩容(扩容阈值=数组容量*加载因子)。
  2. HashMap加入新元素时,如果链表的长度大于8,会将当前链表装换为红黑树。在转换为红黑树之前时,会判断数组长度,如果小于64,会产生数组扩容。如果数组长度大于64,才会将链表转换为红黑树。

扩容多少:HashMap每次扩容时,会按照当前数组的容量扩容2倍。

最大容量:每次HashMap进行扩容时,都会检查当前容量是否超过常量值MAXUMUM_CAPACITY,如果超出,则不扩容。常量值通过位运算1<<30,计算结果为107371824。

三、与HashTable的区别

HashTable是继承自Dictory抽象类。

在没有指定内存大小的时候 ,默认的数组大小是11,扩容是2n+1;

1.底层结构:HashMap和Hashtable的底层结构是都是数组加链表;

2.安全性:HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过synchronized 修饰;

3.对null键和null值的支持:HashMap支持null键和null值,可以有多个null值但只能有一个null键。而HashTable不支持,只要键和值有一个为null就会抛出NullPointerException;

4.效率:因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;

四、LinkedHashMap

HashMap和双向链表(是用于保持迭代顺序)合二为一既是LinkedHashMap。所谓LinkedHasnMap,其实是一个将所有Entry节点链入一个双向链表的HashMap。它是HashMap的子类,所以LinkedHashMap有HashMap的所有特性。

迭代顺序可以是插入顺序,也可以是访问顺序。因此,根据链表中元素的顺序可以将LinkedHashMap分为:保持插入顺序的LinkedHashMap 和 保持访问顺序的LinkedHashMap,其中LinkedHashMap的默认实现是按插入顺序排序的。

 除去红色双向的虚线,就是一个HashMap。

 三、实现类二:TreeMap

TreeMap是SortedMap(父接口为Map)接口的实现类。

使用TreeMap时,放入的Key必须实现Comparable接口。Value没有作要求。

如果作为Key的class没有实现Comparable接口,那么,必须在创建TreeMap时同时指定一个自定义比较器。其默认排序时按照自然排序,对于Integer时按照升序,字符按照字母顺序....

TreeMap不需要用hash来定位元素位置,因为没有使用数组来存储元素。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值