20

以下のコードで構造java.util.ConcurrentModificationExceptionを繰り返し処理するときに何がトリガーされているのかわかりません。LinkedHashMapアプローチを使用すると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();

    }

}
4

6 に答える 6

9

アクセス順のリンクされたハッシュ マップを使用しています: http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.htmlの仕様から、

構造変更とは、1 つ以上のマッピングを追加または削除する操作、またはアクセス順のリンクされたハッシュ マップの場合は反復順序に影響を与える操作です。挿入順リンク ハッシュ マップでは、マップに既に含まれているキーに関連付けられた値を変更するだけでは、構造的な変更にはなりません。アクセス順のリンクされたハッシュ マップでは、get を使用してマップをクエリするだけで、構造が変更されます。)

単純に呼び出すだけgetで、構造的な変更と見なされ、例外がトリガーされます。シーケンスを使用する場合entrySet()、マップではなくエントリのみをクエリしているため、ConcurrentModificationException.

于 2013-04-23T23:19:46.303 に答える
2

Your code

for(String key : lru_cache.keySet()){
    System.out.println(lru_cache.get(key));
}

Actually compiles to:

Iterator<String> it = lru_cache.keySet().iterator();
while (it.hasNext()) {
    String key = it.next();
    System.out.println(lru_cache.get(key));
}

Next, your LRU cache shrinks itself to MAX_SIZE elements not when calling set(), but when calling get() - above answers explain why.

Thus we have following behavior:

  • new iterator created to iterate over lru_cache.keySet() collection
  • lru_cache.get() called to extract element from your cache
  • get() invocation truncates lru_cache to MAX_SIZE elements (in your case 3)
  • iterator it becomes invalid due to collection modification and throws on next iteration.
于 2014-06-23T06:02:00.850 に答える
2

java.util.ConcurrentModificationException: イテレータが存在する間に、基になるリストに構造的な変更 (追加、削除、再ハッシュなど) がある場合。イテレータは、各操作の前にリストが変更されたかどうかを確認します。これは「フェイルセーフ操作」として知られています。

フェイルファスト イテレータを使用してコレクションを繰り返し処理しているときに、スレッドがコレクションを直接変更すると、イテレータはこの例外をスローします。ここでは、イテレータの使用中にメソッドを呼び出すことはできませんget()get()iterators メソッドの 1 つが失敗し、ConcurrentModificationException.

于 2014-06-24T15:14:42.003 に答える
1

このエラーでリストをトラバースしているときに (要素を追加または削除して) リストを変更すると、コレクション フレームワークのフェイル ファスト動作もイテレータで発生します。しばらく前にこのエラーに遭遇しました。詳細については、以下のスレッドを参照してください。

ArrayList の foreach ループ内に追加すると ConcurrentModificationException が発生する

これは配列リストと言っていますが、ほとんどのコレクションのデータ構造に適用されます。

同時変更例外: ArrayList への追加

http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

于 2014-06-23T07:35:31.720 に答える