如果是Java开发者,那么必须知道在使用迭代器完成其所有元素时要修改Collection
对象时出现会出现ConcurrentModificationException
异常。 实际上Java Collection Framework迭代器是迭代器设计模式实现的很好的例子。
Java ConcurrentHashMap
Java 1.5引入了带有Collection
类实现的java.util.concurrent
包,允许在运行时修改集合对象。
ConcurrentHashMap示例
ConcurrentHashMap
类是一个类似于HashMap
的类,但在尝试在运行时修改映射时工作正常。
下面来运行一个示例程序来了解和熟悉,文件:ConcurrentHashMapExample.java –
package com.yiibai.util; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapExample { public static void main(String[] args) { //ConcurrentHashMap Map<StringString> myMap = new ConcurrentHashMap<StringString>(); myMap.put("1" "1"); myMap.put("2" "1"); myMap.put("3" "1"); myMap.put("4" "1"); myMap.put("5" "1"); myMap.put("6" "1"); System.out.println("ConcurrentHashMap before iterator: "+myMap); Iterator<String> it = myMap.keySet().iterator(); while(it.hasNext()){ String key = it.next(); if(key.equals("3")) myMap.put(key+"new" "new3"); } System.out.println("ConcurrentHashMap after iterator: "+myMap); //HashMap myMap = new HashMap<StringString>(); myMap.put("1" "1"); myMap.put("2" "1"); myMap.put("3" "1"); myMap.put("4" "1"); myMap.put("5" "1"); myMap.put("6" "1"); System.out.println("HashMap before iterator: "+myMap); Iterator<String> it1 = myMap.keySet().iterator(); while(it1.hasNext()){ String key = it1.next(); if(key.equals("3")) myMap.put(key+"new" "new3"); } System.out.println("HashMap after iterator: "+myMap); } }
当尝试运行上面的代码时,输出结果如下:
ConcurrentHashMap before iterator: {1=1 5=1 6=1 3=1 4=1 2=1} ConcurrentHashMap after iterator: {1=1 3new=new3 5=1 6=1 3=1 4=1 2=1} HashMap before iterator: {3=1 2=1 1=1 6=1 5=1 4=1} Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)
查看输出,ConcurrentHashMap
负责处理映射中的任何新条目,而HashMap
抛出ConcurrentModificationException
异常。
如果仔细看看异常堆栈跟踪,抛出Exception
的语句是:
String key = it1.next();
这意味着新条目已插入HashMap
,但Iterator
执行失败。 实际上,Collection
对象上的Iterator
是快速的,即结构中的任何修改或集合对象中的条目数都将触发Iterator
抛出的此异常。
那么Iterator
如何知道HashMap
中有一些修改。 从HashMap
中获取了一组键,然后迭代它。
HashMap
包含一个用于计算修改次数的变量,Iterator
在调用next()
函数以获取下一个条目时使用它。
文件:HashMap.java –
/** * The number of times this HashMap has been structurally modified * Structural modifications are those that change the number of mappings in * the HashMap or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). */ transient volatile int modCount;
现在要证明上述观点,在插入新条目时稍微更改代码以从迭代器循环中出来。需要做的就是在put
调用之后添加一个break
语句。
if(key.equals("3")){ myMap.put(key+"new", "new3"); break; }
现在执行修改后的代码,输出将是:
ConcurrentHashMap before iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1} ConcurrentHashMap after iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1} HashMap before iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1} HashMap after iterator: {3=1, 2=1, 1=1, 3new=new3, 6=1, 5=1, 4=1}
最后,如果不添加新条目但更新现有键值对会怎样,它也会抛出异常吗?
更改原始程序中的代码,如下所示 –
//myMap.put(key+"new", "new3"); myMap.put(key, "new3");
这次应该没有问题了。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/264073.html