集合源码之Map

Map

  • Map内存储的是键/值对形式的数据,通过“键”对象来查询“值”对象
  • Map中,key值是唯一的(不能重复),而key对象是与value对象关联在一起的
HashMap
代码一步步解析源码
		Map hashMap = new HashMap();
		hashMap.put("key1","value1");
		hashMap.put("ooookey1","value1");
		hashMap.put("key1","value2");
  1. new HashMap()干了什么:
    指定initial capacity为默认的16,load factor为默认的0.75
  2. hashMap.put()干了什么:
    调用了hashMap的 putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)
    首先判断map的容量是否为0,如果为0,resize为默认的16和0.75的系数。然后用map最大下标-1对hash(key)取余( 也就是源码中(p = tab[i = (n - 1) & hash]) == null 的这一行代码,这里多说一句为什么用按位与,主要是考虑性能,而且不管key的hash值有多大,(n - 1) & hash都不会大于n-1,所以确保不会数组越界),从而判断新key的哈希值是否已经存在。如果不存在,直接创建一个新的Node节点,如果存在,后续会判读equals方法是否相同,也就是所说的hash冲突引起的碰撞探测,具体参照5. 解决hash冲突。判断onlyIfAbsent参数是否为false(true为不替换存在的value,默认为false),替换掉已经存在的key对于的value。
  3. hashMap是无序的:和put的顺序无关
  4. hashMap的resize方法:
    顾名思义初始化或扩容hashMap的容量,当hashMap中填满了容量得75%的时候,就会去扩容,首先确定 新容量的大小,也就是 旧容量翻倍(oldCap << 1),然后将容量阈值threshold设置为新的容量值 * 0.75,最后将之前的Node数组循环遍历(由此可见map的底层实现是数组),复制放进新的数组中。
  5. 解决hash冲突:
    HashMap使用链表的方式避免哈希冲突(相同的hash值),当链表长度大于 TREEIFY_THRESHOLD (默认为8)的时候,将链表转换成红黑树;当小于UNTREEIFY_THRESHOLD (默认为6)的时候,又会转回链表以达到性能均衡。
    hashMap的node节点中有一个next,这个参数就是记录如果hash碰撞后,hash值相同时链表结构中下一级Node节点。在这里插入图片描述

在这里插入图片描述
如果同一个hash值下,链表的长度大于8时,将链表结构转换为红黑树,也就是下面的TreeNode
在这里插入图片描述

hashMap中的数据存储概览图
在这里插入图片描述

Hashtable
  1. Hashtable继承于古老的Dictionary类
  2. Hashtable是线程安全的
  3. Hashtable键值不可为空
  4. Hashtable的任何操作都会把整个表锁住,是阻塞的。好处是总能获取最实时的更新,比如说线程A调用putAll写入大量数据,期间线程B调用get,线程B就会被阻塞,直到线程A完成putAll,因此线程B肯定能获取到线程A写入的完整数据。坏处是所有调用都要排队,效率较低。
ConcurrentHashMap
核心原理
  1. 底层实现和hashMap一样,通过数组+链表+红黑树实现
  2. 通过CAS+synchronized关键字来保证并发安全
代码解析
        ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();
        concurrentHashMap.put("key1","value1");
        concurrentHashMap.put("key2","value1");
        concurrentHashMap.remove("key3");
        concurrentHashMap.get("key2");

1、初始化:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值