这里我采用的分析方式是帖子博客加上自己翻看jdk源码。有些情况下写一些测试的算法小例子加深印象。我这里只描述一下自己的总结想法
上一篇文章我们研究了set接口下的几个容器,由于其Set集合设计时底层的数据模型是Map,Set的实现是基于Map的、所以先搞懂Map、才能去理解Set、否则的话、直接去弄Set会觉得云里雾里、最后发现是浪费时间。这一节介绍关于Map的相关接口、抽象类的功能。
一、Map集合结构体系图(网络图,侵删)
这篇文章主要对TreeMap,HashMap和LinkedHashMap做分析,其他不常用的先不进行分析,另外针对HashTable和ConcurrentHashMap这两个线程安全的Map着重开一章去整理
二、源码分析
1、HashMap源码分析
上帖子:http://www.cnblogs.com/chengxiao/p/6059914.html
总结:
(1)首先重点了解一下哈希表的数据结构,
哈希表(散列)主要利用数组和链表的方式。利用这种方式就可以避免单个数组出现的修改删除的高时间复杂度,又避免了聊表查询的高时间复杂度,具体实现方式请参看上边的博客,具体的讲解了目前的主要数据结构以及哈希表结构
(2)知道了哈希表的数据结构,就能理解HashMap的存储方式了,HashMap就是利用数组+链表的方式进行数据存储。博客中也对主要的添加,删除,修改方法进行了源码详解。在看源码的过程中注意细节
- 方法没有加锁,所以对于hashMap来说,是线程不安全的集合
- 数组是如何扩容的,扩容的算法如博客 http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html
- 对于hash碰撞是如何处理的,
Hashmap里面的bucket出现了单链表的形式,散列表要解决的一个问题就是散列值的冲突问题,通常是两种方法:链表法和开放地址法。链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位;开放地址法是通过一个探测算法,当某个槽位已经被占据的情况下继续查找下一个可以使用的槽位。java.util.HashMap采用的链表法的方式,链表是单向链表。
hash碰撞的产生和解决:http://blog.csdn.net/luo_da/article/details/77507315 - hash与hashCode的重写
重写对象的equels必须重写hashCode方法,不然比对后无法识别是不是同一个对象
hashCode重写例子:http://blog.csdn.net/woshixuye/article/details/8189398
2、LinkedHashMap源码分析
发布一个描述LinkedHashMap的博客:http://www.cnblogs.com/chenpi/p/5294077.html
- LinkedHashMap继承了HashMap,在它的构造方法中调用的都是父类HashMap的构造方法
- LinkedHashMap也采用数组加链表的方式,只不过LinkedHashMap在散列表基础上多维护了一个有序双向链表,所以LinkedHashMap支持排序。可以按照插入循序排序和访问数序排序
源码分析:http://www.cnblogs.com/chenpi/p/5294077.html - LinkedHashMap同样没有同步方法,不支持线程安全
- hash碰撞原理同于HashMap
3、TreeMap源码分析
发布一个描述TreeMap的博客:http://www.cnblogs.com/wzyxidian/p/5204879.html
- TreeMap是采用一个“红黑树”的数据结构进行存储,存储对象对拥有它的父节点,左孩子,右孩子,具体的二叉树的实现原理请参考博客中有详解,这里不做过多解析
- TreeMap是线程不安全的
三、区别对比
1、相同点
- 都是线程不安全的
- LinkedHashMap和HashMap都是采用散列表的结构进行数据存储
2、不同点
- TreeMap存储方式采用链表的方式进行存储,而LinkedHashMap和HashMap采用散列表的结构存储
- HashMap存储是无序的,LinkedHashMap可以按照插叙顺序排序,TreeMap按照key的自然排序或者自定义排序(只需要key定制排序Comparator )
四、总结
三种类型分别在什么时候使用
1、一般情况下,我们用的最多的是HashMap。HashMap里面存入的键值对在取出的时候是随机的,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
2、TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
3、LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列,像连接池中可以应用。