HashMap并发修改异常,或者循环时删除异常
ConcurrentModificationException
基本都是modCount修改后与原modCount不相等而暴露的异常。很多集合都会有这个问题
编写者抛这个异常的是想 快速失败,暴露异常。让开发者自己解决
当我们在for循环map 时,会编译成迭代器的方式 去运行。而删除我们调用的是hashmap自身的remove方法。
HashMap<Integer, String> host = new HashMap();
host.put(1, "2");
host.put(2, "2");
host.put(3, "2");
Iterator var2 = host.keySet().iterator();
while(var2.hasNext()) {
Integer integer = (Integer)var2.next();
if (integer.equals(1)) {
host.remove(integer);
}
}
var2.next() 这行代码执行时 会判断count而报错。 解决方法就是 用 迭代器的remove 方法,会在remove时重新给modCount赋值
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
removeNode(p.hash, p.key, null, false, false);
expectedModCount = modCount;
}
这个不是线程安全的,所以并发还是用ConcurrentHashMap
HashMap 底层结构
1.7:数组+链表 (由于是链表长度长了。查询效率不高。所以在设计初衷1.7的hash算法更复杂。数据也更散列)
1.8:数组+链表+红黑树(JDK8中即使用了单向链表,也使用了双向链表,双向链表主要是为了红黑树相关链表操作方便,应该在插入,扩容,链表转红黑树,红黑树转链表的过程中都要操作链表)
![](https://yakax.oss-cn-hangzhou.aliyuncs.com/blog/sets/QQ%E6%88%AA%E5%9B%BE20200905112823.png)
HashMap 转红黑条件
只有当链表中的元素个数大于8(此时 node有9个),并且数组的长度大于等于64时才会将链表转为红黑树。
// putVal 片段
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) =&