HashMap环 JDK1.7
2017-12-04 21:06
141 查看
HashMap是非线程安全的,主要是在扩容时,会产生错误。
源码如下:
输入5,7,3,形成如下:
![](https://img-blog.csdn.net/20171204201705691?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
正常扩容之后:
![](https://img-blog.csdn.net/20171204201725073?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
时,CPU切换到B,执行了扩容,并且扩充完毕,如上图,正常扩容之后的图。
此时CPU再切换到A,执行如下:
![](https://img-blog.csdn.net/20171204202417481?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
再往下执行:
![](https://img-blog.csdn.net/20171204202736522?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
再往下执行:
![](https://img-blog.csdn.net/20171204203950394?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
即3的next是7,7的next是3,由此形成环,在查询的时候,会陷入“死循环”。
最后插入5,放在第二个,没有影响。
![](https://img-blog.csdn.net/20171204210225395?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjcxODA1NjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
按照以上思路分析,不难得出结论,元素3最后会丢失。
源码如下:
/** * 扩容 */ void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor); } /** * 构造新数组 */ void transfer(Entry[] newTable) { Entry[] src = table;// 原数组 int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j];// e为原数组中的元素 if (e != null) { src[j] = null; do { Entry<K,V> next = e.next;// 当前元素的后一个元素 int i = indexFor(e.hash, newCapacity); e.next = newTable[i];// 头元素后移(头元素都在数组中) newTable[i] = e; // 当前元素为头元素 e = next; } while (e != null); } } }
输入5,7,3,形成如下:
正常扩容之后:
链表环
现存在两个线程A和B,当A执行到Entry<K,V> next = e.next;
时,CPU切换到B,执行了扩容,并且扩充完毕,如上图,正常扩容之后的图。
此时CPU再切换到A,执行如下:
Entry<K,V> next = e.next;// e=3,next=7 e.next = newTable[i];// e.next=null newTable[i] = e; // newTable[i]=3 e = next;// e=7
再往下执行:
Entry<K,V> next = e.next;// e=7,next=3(参照B扩容后的链表) e.next = newTable[i];// e.next=3 newTable[i] = e; // newTable[i]=7 e = next;// e=3
再往下执行:
Entry<K,V> next = e.next;// e=3,next=null(参照B扩容后的链表) e.next = newTable[i];// e.next=7 newTable[i] = e; // newTable[i]=3 e = next;// e=null
即3的next是7,7的next是3,由此形成环,在查询的时候,会陷入“死循环”。
最后插入5,放在第二个,没有影响。
元素丢失
输入3,5,7,行程如下:按照以上思路分析,不难得出结论,元素3最后会丢失。
相关文章推荐
- [置顶] JDK1.7 HashMap集合源代码探索
- 基于jdk1.7的hashmap
- JDK1.7版本中的HashMap
- jdk1.7和jdk1.8中hashmap区别
- JDK1.7中HashMap的常用方法实现原理
- 【JAVA秒会技术之ConcurrentHashMap】JDK1.7与JDK1.8源码区别
- JDK1.7与JDK1.8中ConcurrentHashMap原理总结
- jdk1.7和jdk1.8中hashmap区别
- 基于JDK1.7的HashMap源码阅读分析
- JDK1.7 中的HashMap源码分析
- JDK1.7的HashMap源码
- JDK1.7 HashMap 源码分析
- JDK1.7的HashMap的put(key, value)源码剖析
- jdk1.7之HashMap
- c语言实现通用数据结构(五):通用映射(HashMap)
- Hashmap原理加原代码
- Java - Hash - HashMap与HashTable
- HashMap的理解
- 关于HashMap和LinkedHashMap
- Java HashMap遍历实践