Java常见集合类三(Map,HashMap put 方法详解)

一、Map 接口概述

a5956d7463ca4e83906b73d425d08d47.png

Map 中存放键值对的 key 是唯一的,value 是可以重复的;

Map 中的 key 可以全部分离出来,存储到 Set 中来进行访问 (因为 key 不能重复);

Map 中的 value 也可以全部分离出来,存储在 Collection 集合中 ( value 可能有重复);

Map中键值对的 key不能直接修改,value 可以修改,如果要修改 key,只能先将该 key 删除掉,然后再来进行重新插入。 

Map 接口常用方法:

1bcc92ea2b874148af79946e3eb59b21.png

 二、Map.Entry<K, V>

Map.Entry 是 Map 内部实现的用来存放键值对映射关系的内部类(实际是接口),该内部类中主要提供了<key, value> 的获取,value 的设置以及 key 的比较方式。方法为:

9c7f82e8324246dca95b9407fc9ecf0d.png

三、HashMap

a8da99ad58a74ab69f0ba397d00bf40a.png

HashMap 中的 key 和 value 都可以为空,key 不能重复,是线程不安全的。

底层数据结构:数组 + 链表 / 红黑树(JDK 1.8及以后)

常用构造方法:

04b7fc4b23d347969b0d310db063e94c.png

1. 构造一个空的 HashMap 对象,初始容量为16,加载因子为 0.75;

2. 构造一个空的 HashMap 对象,初始容量为指定的容量(第一个大于指定容量的二次幂),加载因子为 0.75;

4. 构造一个包含实现了 Map 接口的子类的 HashMap 对象;

HashMap 使用懒加载,在进行第一次 put 操作时才会初始化 table(在没有进行 put 操作的时候 table 为 null );

常用其他方法:

1. put(K key, V value):存放 key,value 键值对;

1)首先根据 hash() 方法计算 key 对应的 hash值;

58f986fa14ec4c8097c2102b32f58fd6.png

2)调用 putVal() 方法来进行插入;

9ff88f6185564711b4f35a32f7ab76b4.png

a. 首先会判断 table 是否为空(第一次 put 的时候),通过resize() 方法来进行初始化;默认容量大小为16,加载因子为 0.75;即当 table 中的数据达到此时的最大容量 16 * 0.75 = 12 时,会触发扩容机制,默认扩容为原来最大容量的 2 倍;

45758c433a3a49d7a704210cfc0480a7.png

b. 判断是否产生冲突,根据由 key 计算的 hash 值在 node 数组中对应位置是否有元素来判断;

1. 如果没有元素,则直接在创建一个新的节点存放在 node 数组中;

448295e6d2a44a5a80ec13f040957a8a.png

2. 如果有元素,判断 key 计算的 hash 以及 通过 == 判断或者 equals 判断 key 是否都相等(与 table数组索引位置处的值判断);如果相等说明此时插入的 key 是重复的,替换掉原来的 value;

420310ed03eb4a6ba46e124286037b31.png

3. 如果经过 2 判断不成立,此时会判断当前数组位置上对应的节点类型是否为 TreeNode(即判断当前链表是否已经树化),如果已经树化了,则按照红黑树的插入执行; 

a3cc125e553a45439c626ee24be69a77.png

4. 经 3 判断过之后,说明此时链表还没有树化,则会遍历该数组位置上的链表,

a:判断链表上的每个节点和当前要插入的节点的 key 算出的 hash 值是否相等,

b:并且 key 相等或者通过 equals 判断相等,如果都判断相等,则跳出循环,不再添加新节点(对应第二个 if 判断);

否则(对应第一个 if 判断),会创建一个新的节点(将其key,value等值赋值到新节点上)插入到链表的最后;插入完成后,判断是否达到树化的条件(数组长度大于等于 64 并且某一条链表的长度大于等于 8),若满足条件,则进行树化;

最后的 if 判断,进行 value 值的替换。

25fc5139e5d844ecbd51d8c4b8be3d94.png

c. 最后插入完成后,判断是否达到了扩容的条件(table 中的总数据量达到临界值即 最大容量 * 加载因子),来决定是否需要进行扩容(通过 resize 方法扩容);

3dc1631d365042a79edecc6d1dd7f8a3.png

2. get(K key):根据 key 获取 value

305839304b3c43faa94f8ff23cf124c9.png

通过调用 getNode 方法实现

02252d71c76344e0bbfda06a494e3ef4.png

1)首先判断 table 数组不为空,并且 table 数组的长度 不为 0,并且通过 hash 算法计算出 key 在table 表中的位置不为空,若不满足以上条件,则直接返回 null,也就是说 key 是不存在的;(对应第一个 if )

2)满足 1 之后,(对应第二个 if )

a:判断该 key 的hash值与  key 在 table 数组中对应位置的链表的第一个元素计算的 hash值  是否相等,

b: 通过 == 判断的 key 相等 或者 通过 equals 方法判断相等,

若满足 a 和 b,则说明该 table 数组位置上的链表的第一个节点就是要查询的节点;

3)不满足 2 之后,判断 这个链表的下一个节点是否为空,(对应第三个 if )

a:如果为空,说明链表只有一个节点并且不满足,则返回空,

b:如果不为空,判断其类型是否为 TreeNode,即判断是否已经树化(对应第四个 if ),若树化,则按照红黑树的方式进行查询,如果不为 TreeNode,则循环判断该链表上的每个节点是否满足 2 的条件,若满足则返回该节点,否则,一直判断直到该节点为 null;

3. containsKey(Object key)(通过getNode 方法判断)

ff3236ccc225485e92ed8c800414868d.png

4. 其他常用方法在 Map 接口常用方法 中;

四、TreeMap 

df680707cfb64156ad8d19fc1e7b22bf.png

TreeMap 中的 key 不可以为空,value 可以为 null,key 不能重复,是线程不安全的。

底层使用红黑树,查询的时间复杂度为 O (logn)

常用构造方法:

794d3c2d07cb4f148129964fbe4942e3.png

1. 创建一个空的 TreeMap 对象,使用其 key 的自然排序规则排序;

2. 创建一个空的 TreeMap 对象,使用指定的比较器进行排序;

3. 创建一个TreeMap 对象,其包含一个实现了 Map 接口的类的对象,使用 key 的自然排序规则排序;

其他常用方法:

1. Comparator<? super K> comparator():返回该映射中用于排序的比较器对象,若使用自然排序则返回 null;

2. 其他常用方法在 Map 接口常用方法 中;

五、HashMap 和 TreeMap 区别

3475f21e541147618928b2be3dbeb1bd.png

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rcnhtin

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

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

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

打赏作者

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

抵扣说明:

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

余额充值