上文讲到HashMap的增长方法,如今继续 上文连接html
HashMap在上一篇源码分析的文章中,若是使用put的时候若是元素数量超过threshold就会调用resize进行扩容java
想要了解HashMap的扩容机制你要有这两个问题数组
在添加元素的时候若是超过threshold设置的阀值点就会进行扩容,简单的来讲就是一个水壶容量是二升,而后这个时候已经满了可是你还要继续加水,咋办?换个大的。因此HashMap的扩容就和你这个水壶同样,水已经满了那我就在换个大的水壶继续加水。不过在你换水壶的时候是有不少条件的。安全
在我看这个resize的源码的时候我也是一脸懵逼,最后请教了大佬获得的回答是由于1.8加入了红黑树比较麻烦能够看一下1.7的,而后我有去网上看了一下别人写的文章基本上都是基于1.7的resize。因此这里就看1.7的resize来分析。数据结构
来看JDK1.7中resize的实现。源码分析
复制操做是调用的transfer方法线程
在1.7中的resize结合一下咱们的小例子能够这样理解,去超市买一个大一点的水壶,而后把之前水壶里面的水给倒进新的水壶里面。再把咱们当前的水壶的容量替换掉,告诉别人个人容量更大了。(强行比喻哈哈哈哈哈)3d
1.7中的resize就是这么简单,那咱们在看一下1.8中的resize(),这样再看就不会一脸懵逼了code
我在这里把1.8的resize方法分为两部分htm
第一部分
第二部分
对比一下1.7
删除的话就是首先先找到元素的位置,若是是链表就遍历链表找到元素以后删除。若是是用红黑树就遍历树而后找到以后作删除,树小于6的时候要转链表。
删除方法:
调用removeNode:
查找方法,经过元素的Key找到Value。
调用getNode()方法
看完能够知道逻辑是先经过Key计算出索引的位置,而后先检查第一个节点看看是不是咱们要的节点,若是不是在去查看是否死红黑树和链表。
咱们经过下面几个例子来演示一下HashMap怎么遍历
1.分别遍历Key和Values
for (String key:map.keySet()){ System.out.println(key); } for (Object value : map.values()) { System.out.println(value); }
2.迭代
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> mapEntry = iterator.next(); System.out.println(mapEntry.getKey() + "====" + mapEntry.getValue()); }
3.获取 key 集合
Set<String> keySet = map.keySet(); for (String str : keySet) { System.out.println(str + "====" + map.get(str)); }
4.获取Entry 集合,遍历Entry 集合
Set<Map.Entry<String, Object>> entrySet = map.entrySet(); for (Map.Entry<String, Object> entry : entrySet) { System.out.println(entry.getKey() + "====" + entry.getValue()); }
对比来讲使用迭代的方式是最好的,也能够在迭代的时候对集合的元素进行删除
基于JDK1.8的HashMap是由数组+链表+红黑树组成,当链表长度超过 8 时会自动转换成红黑树,当红黑树节点个数小于 6 时,又会转化成链表。相对于早期版本的 JDK HashMap 实现,新增了红黑树做为底层数据结构,在数据量较大且哈希碰撞较多时,可以极大的增长检索的效率。HashMap并非线程安全的,支持K和V为null ,k重复会覆盖,V能够重复,还有一点HashMap遍历的数据不是有序的是无序的