当我遍历下面代码中的 LinkedHashMap
结构时,不确定是什么触发了 java.util.ConcurrentModificationException
。使用 Map.Entry
方法效果很好。没有从以前的帖子中得到关于触发此问题的良好解释。
如有任何帮助,我们将不胜感激。
import java.util.LinkedHashMap;
import java.util.Map;
public class LRU {
// private Map<String,Integer> m = new HashMap<String,Integer>();
// private SortedMap<String,Integer> lru_cache = Collections.synchronizedSortedMap(new TreeMap<String, Integer>());
private static final int MAX_SIZE = 3;
private LinkedHashMap<String,Integer> lru_cache = new LinkedHashMap<String,Integer>(MAX_SIZE, 0.1F, true){
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return(lru_cache.size() > MAX_SIZE);
}
};
public Integer get1(String s){
return lru_cache.get(s);
}
public void displayMap(){
/**
* Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:384)
at LRU.displayMap(LRU.java:23)
at LRU.main(LRU.java:47)
*/
*for(String key : lru_cache.keySet()){
System.out.println(lru_cache.get(key));
}*
// This parser works fine
// for(Map.Entry<String, Integer> kv : lru_cache.entrySet()){
// System.out.println(kv.getKey() + ":" + kv.getValue());
// }
}
public void set(String s, Integer val){
if(lru_cache.containsKey(s)){
lru_cache.put(s, get1(s) + val);
}
else{
lru_cache.put(s, val);
}
}
public static void main(String[] args) {
LRU lru = new LRU();
lru.set("Di", 1);
lru.set("Da", 1);
lru.set("Daa", 1);
lru.set("Di", 1);
lru.set("Di", 1);
lru.set("Daa", 2);
lru.set("Doo", 2);
lru.set("Doo", 1);
lru.set("Sa", 2);
lru.set("Na", 1);
lru.set("Di", 1);
lru.set("Daa", 1);
lru.displayMap();
}
}
最佳答案
A structural modification is any operation that adds or deletes one or more mappings or, in the case of access-ordered linked hash maps, affects iteration order. In insertion-ordered linked hash maps, merely changing the value associated with a key that is already contained in the map is not a structural modification. In access-ordered linked hash maps, merely querying the map with
get
is a structural modification.
由于您传入 true
到 LinkedHashMap
构造函数,它在访问顺序中,当你试图 get
从它的某些东西,你正在结构上修改它。
另请注意,当您使用增强的 for
时语法,您实际上是在使用迭代器。来自 JLS §14.14.2 的简化报价:
The enhanced
for
statement has the form:EnhancedForStatement: for ( TargetType Identifier : Expression ) Statement
[...]
If the type of Expression is a subtype of
Iterable<X>
for some type argumentX
, then letI
be the typejava.util.Iterator<X>
; otherwise, letI
be the raw typejava.util.Iterator
.The enhanced
for
statement is equivalent to a basicfor
statement of the form:for (I #i = Expression.iterator(); #i.hasNext(); ) { TargetType Identifier = (TargetType) #i.next(); Statement }
#i
is an automatically generated identifier that is distinct from any other identifiers (automatically generated or otherwise) that are in scope (§6.3) at the point where the enhanced for statement occurs.
此外,在 LinkedHashMap
的 Javadoc 中:
The iterators returned by the
iterator
method of the collections returned by all of this class's collection view methods are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's ownremove
method, the iterator will throw aConcurrentModificationException
.
因此,当您调用 get
时在 map 上,您正在对其进行结构修改,导致增强型 for 中的迭代器抛出异常。我认为你打算这样做,这样可以避免调用 get
:
for (Integer i : lru_cache.values()) {
System.out.println(i);
}
关于java - LinkedHashMap 的 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16180568/