集合(四)Map 先导篇

HashMap要点概括

参考文献:

https://blog.csdn.net/qq_27093465/article/details/52207135

http://zhangshixi.iteye.com/blog/672697 
http://blog.csdn.net/lizhongkaide/article/details/50595719

https://blog.csdn.net/qq_25868207/article/details/55259978

  1. HashMap是基于哈希表的Map接口的非同步实现,允许使用null值和null键,但不保证映射的顺序。
  2. 底层使用数组实现,数组中每一项是个单向链表,即数组和链表的结合体;当链表长度大于一定阈值时,链表转换为红黑树,这样减少链表查询时间。
  3. HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Node对象。HashMap底层采用一个Node[]数组来保存所有的key-value对,当需要存储一个Node对象时,会根据key的hash算法来决定其在数组中的存储位置(会对key进行hash(),高位运算,取模运算—— 因为数组的长度永远都是2的几次幂,所以相当于对数组长度-1 求&,从而得出数组下标
  4. 判断一下当前数组是否为空,如果是空,直接插入,如果存在,直接覆盖。否则,说明发生了碰撞,先判断一下是不是红黑树,不是的话遍历链表,准备插入。如果连遍长度大于8,转换成红黑树插入键值对。否则遍历插入。在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Node时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Node。
  5. threshold = length*load factor( 负载因子:默认0.75)。如果插入后的数组实际拥有元素个数——size >threshold则进行扩容,初始化一个新数组,并将原数组所有内容拷贝至新数组。要重新计算每个元素在新数组中的位置,扩容后的新数组长度总是当前长度的2倍,所以扩容后原数组上的元素的位置不是在新数组的原位置上,就是在新数组的原位置+旧容量的位置上。jdk1.8进行了很好的优化处理。另外jdk1.7之前都是采用头插,会使得插入的顺序倒置,jdk1.8不会了。
  6. 采用了Fail-Fast机制,通过一个modCount值记录修改次数,对HashMap内容的修改都将增加这个值。迭代器初始化过程中会将这个值赋给迭代器的expectedModCount,在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了Map,马上抛出异常

具体分析做了思维导图可以查看: https://blog.csdn.net/uknowzxt/article/details/80353122

Hashtable要点概括

参考文献:

http://blog.csdn.net/zheng0518/article/details/42199477

https://blog.csdn.net/qq_25868207/article/details/55259978

  1. Hashtable是基于哈希表的Map接口的同步实现,不允许使用null值和null键
  2. 底层使用数组实现,数组中每一项是个单链表,即数组和链表的结合体
  3. Hashtable在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
  4. synchronized是针对整张Hash表的,即每次锁住整张表让线程独占

ConcurrentHashMap要点概括

参考文献:

http://blog.csdn.net/zheng0518/article/details/42199477

https://blog.csdn.net/qq_25868207/article/details/55259978

  1. ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。
  2. 它使用了多个锁来控制对hash表的不同段进行的修改,每个段其实就是一个小的hashtable,它们有自己的锁。只要多个并发发生在不同的段上,它们就可以并发进行。
  3. ConcurrentHashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
  4. 与HashMap不同的是,ConcurrentHashMap使用多个子Hash表,也就是段(Segment)
  5. ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。如果使用传统的技术,如HashMap中的实现,如果允许可以在hash链的中间添加或删除元素,读操作不加锁将得到不一致的数据。ConcurrentHashMap实现技术是保证HashEntry几乎是不可变的。

具体分析可以查看: https://blog.csdn.net/uknowzxt/article/details/82931213

LinkedHashMap要点概括

参考文献:

https://blog.csdn.net/qq_19431333/article/details/73927738

https://blog.csdn.net/qq_25868207/article/details/55259978

https://www.cnblogs.com/lzrabbit/p/3734850.html

  1. LinkedHashMap继承于HashMap,底层使用哈希表和双向链表来保存所有元素,并且它是非同步,允许使用null值和null键。
  2. 基本操作与父类HashMap相似,通过重写HashMap相关方法,重新定义了数组中保存的元素Entry,来实现自己的链接列表特性。该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而构成了双向链接列表。
  3. LinkedHashMap默认是按照插入顺序存储的,但是一旦在构造方法中传入accessOrder为true,那么在访问某一节点的时候,会将该节点移动到双端链表的尾部。
  4. 另外如果重写LinkedHashMap的removeEldesEntry(Map.Entry<K,V> eldest)方法,使其有机会返回true,那么将有机会删除最老元素(first)
  5. 根据3、4两点特性,使得LinkedHashMap可以实现LRU缓存。

具体分析可以查看: https://blog.csdn.net/uknowzxt/article/details/82916976

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值