java.util.ConcurrentModificationExceptionが発生する原因と回避方法

このQ&Aのポイント
  • ConcurrentModificationExceptionという例外が発生してしまいます。どうすれば回避できるのでしょうか?
  • この例外は、特定の操作をすると必ず発生しますが、他の操作では発生しません。原因がわかりません。
  • synchronizedやiterator.removeを使用しても問題が解決せず、どのような対策が効果的でしょうか?
回答を見る
  • ベストアンサー

java.util.ConcurrentModificationExceptionが発生します。

ConcurrentModificationExceptionという例外が発生してしまいます。 for (String extDefId : ansExtDefForInputMapResult.keySet()) { if (!ansExtDefForInputMap.containsKey(extDefId)) { ansExtDefForInputMapResult.remove(extDefId); } } というコードを書いています。 どうすれば回避できるのでしょうか? synchronizedでくくったり、iterator.removeを使ったりしてみましたがだめでした。 この例外は、ある操作をすると必ず発生しますが、同じコードは通るが別の操作をすると発生しません。原因がさっぱりわかりません。

  • Java
  • 回答数1
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.1

 こんにちは。  反復子を使ってる最中にマップの中身をつつくと不整合が発生するので、その例外が出ます。  ちゃんと iterator.remove()を使えば、例外は出ませんよ。 (コンパイルするときは全角スペースを半角スペースに変換してからにしてください) import java.util.*; public class Main {   /**    * @param args the command line arguments    */   public static void main(String[] args) {     HashMap<String, String> ansExtDefForInputMapResult = new HashMap<String, String>();     ansExtDefForInputMapResult.put("a", "A");     ansExtDefForInputMapResult.put("b", "B");     ansExtDefForInputMapResult.put("c", "C");     HashMap<String, String> ansExtDefForInputMap = new HashMap<String, String>();     ansExtDefForInputMap.put("a", "A");     ansExtDefForInputMap.put("c", "C");     for (Iterator<String> iterator = ansExtDefForInputMapResult.keySet().iterator(); iterator.hasNext();) {       String extDefId = iterator.next();       if (!ansExtDefForInputMap.containsKey(extDefId)) {         iterator.remove();       }     }     System.out.println(ansExtDefForInputMapResult);   } }

kotoby2003
質問者

お礼

ありがとうございます! ただ、自己解決してました。 というか、こちらのサイトを見つけたので。 http://www.eeb.co.jp/2008/01/_36_foriterator.html OKWaveって、自己回答ができないんですよね・・・。

関連するQ&A

  • ListからMapを作成 MapのValueにはListをput

    すみません、どなたか教えて下さい。 あるListからMapを作成したく、同じkeyが存在する場合、valueのListへ値を追加したいですのですがConcurrentModificationExceptionエラーが返されてしまいます。エラーを返さないように変数を使い分け工夫したつもりですが。。。((1)でmapAにもaddされている!?)他に良い方法はないでしょうか? Map mapA = new TreeMap(); Map mapB = new TreeMap(); Iterator it = listA.iterator(); while (it.hasNext()) { Bean bean = (Bean)it.next(); List mapvaluelist = new ArrayList(); if (mapA.size()==0){ mapvaluelist.add(bean); mapA.put(bean.getName(),mapvaluelist); }else{ if (mapB.size()!=0){ mapA = mapB; } Set keyset = mapA.keySet(); Iterator itmap = keyset.iterator(); while (itmap.hasNext()){ String mapkey = (String)itmap.next(); if (bean.getName().equals(mapkey)){ mapvaluelist = (List)mapA.get(mapkey); mapvaluelist.add(bean); mapB.put(bean.getName(),mapvaluelist); (1) }else{ mapvaluelist.clear(); mapvaluelist.add(bean); mapB.put(bean.getName(),mapvaluelist); } } } }

  • 配列を大きい順にソートしたいのですが・・・

    次の配列のc.intValue()が回数表示されるのですが、 あまりにデータが多いため、見やすくするために数が大きい順に表示したいと思います。 for文でlengthを求め・・・って言うのは分かるのですが、 c.intValue()で表示にしているので、どう書けばいいか分かりません。 以下ソースです。 ・・・・・ HashMap<String,Integer> hsFlow = new HashMap<String,Integer>(); <中略> Iterator<String> ir = hsFlow.keySet().iterator(); while(ir.hasNext()){ String f = ir.next(); Integer c = hsFlow.get(f); if(c==null) c = new Integer(0); System.out.println("経路"+f+":"+c.intValue()+"回"); 具体的なソースコードを教えていただけると嬉しいです。 ご回答よろしくお願いします。

    • ベストアンサー
    • Java
  • java.util.Comparatorのcompareメソッドの振る舞いについて

    はじめまして。 質問をさせていただきます。 以下のソースで、 =============================================================== import java.util.Comparator; import java.util.TreeSet; import java.util.Iterator; final class Demo { public static void main(String[] args) { TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() { public int compare(Integer i,Integer j) { int result = i%2 - j%2; if(result==0) { result = i-j; } return result; } }); for(int i=0;i<10;i++) { set.add(10-i); } Iterator<Integer> it = set.iterator(); while(it.hasNext()) { System.out.println((Integer)it.next()); } } } ================================================================ 実行結果 ================================================================ 2 4 6 8 10 1 3 5 7 9 ================================================================ 偶数が最初に昇順で出力され、奇数が後から昇順で出力されている のですが、なぜこのような実行結果になるのかがわかりません。 どうかご教授お願いします。

    • ベストアンサー
    • Java
  • Java。以下のソースをご覧下さい。

    配列ですが、現在の一覧表示を上位10件で表示したいのですが、教わって書いたソースのため、どう手をくわえればいいか分かりません・・・ ご教示お願いします。 //以下ソースです。ほぼ表示ロジックのみですが、足りなければ別途追記致します。 <前略> Iterator<String> ir = hsFlow.keySet().iterator(); while(ir.hasNext()){ ArrayList<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(); list.addAll((new HashMap<String,Integer>(hsFlow)).entrySet()); Collections.sort(list,Collections.reverseOrder(new SampleSorter())); for(Map.Entry<String,Integer> m:list){ System.out.println(m.getKey()); System.out.println(m.getValue()); String f = ir.next(); Integer c = hsFlow.get(f); if(c==null) c = new Integer(0); System.out.println("回数"+f+":"+c.intValue()+"回"); //この回数表示の部分で回数の多い上位10件のみの表示にしたいと思っています。

    • ベストアンサー
    • Java
  • 反復的削除時に発生するConcurrentModificationExceptionのスマートな回避

    次のコードのように反復中にそのコレクションを削除しようとすると、ConcurrentModificationExceptionが発生してしまいます。 Set<Integer> set = new HashSet<Integer>(); for (int i = 0 ; i < 10 ; i++) {  set.add(i); } // このループで例外発生 for (Integer currValue : set) {  if (currValue % 2 == 0) {   set.remove(currValue);  } } for (Integer currValue : set) {  System.out.println(currValue + " "); } これを回避するために、反復中に削除せず、削除対象をまず保持しておき、その後でまとめて削除するという方法です。 Set<Integer> set = new HashSet<Integer>(); Set<Integer> removeReserve = new HashSet<Integer>(); for (int i = 0 ; i < 10 ; i++) {  set.add(i); } for (Integer currValue : set) {  if (currValue % 2 == 0) {   removeReserve.add(currValue);  } } for (Integer currValue : removeReserve) {  set.remove(currValue); } for (Integer currValue : set) {  System.out.println(currValue + " "); } しかしこの方法だと、ループがもう一度増えてしまい、なんだか気持ちよくありません。 そこで、もしももっとよい解決策の考え方があれば、教えて頂きたいのです。 「この方法以外ないと思う」という意見もほしいです。 その場合は、上記の解決策にしようと思います。

    • ベストアンサー
    • Java
  • javaプログラミング

    JAVAプログラミングです。 教えてください 次のコードを実行すると、 「ary= new int[-5]; 」では例外が発生するのでtry文を用いてこの例外に対する例外処理をしたいんですがどう書けばいいですか?プログラムを実行した後に[例外処理後の実行例〕になるようにしたいです。 〔NegativeArraySizeException 例外を発生するコード〕 class Assignment9_1 { public static void main(String[] args) { int[] ary; // 例外 NegativeArraySizeException が発生 ary=new int[-5]; } } 〔例外処理前の実行結果〕 Exception in thread "main" java.lang.NegativeArraySizeException at Assignment9_1.main(Assignment9_1.java:7) 〔例外処理後の実行例〕 配列要素数の指定は負です

    • ベストアンサー
    • Java
  • HashSetのremoveで例外発生します

    JavaでObjectの保存メソッドを作成したのですが、「java.util.ConcurrentModificationException : null」が発生します。 処理としては、引数のObjectが持っている情報(リスト)と本来登録すべきデータリストを照らしあわせ、追加する必要があるものはaddオブジェクトに削除する必要があるものはdelオブジェクトに残すようにし、最終的にDBデータの追加、削除を実行しています。 おそらく、delHogeIdSet.removeの記述の問題なのではと思ってはいるのですが、改変する良い方法がわかりません。 Hash自身をチェックしてremoveするならiteratorでよいのかもしれませんが、チェックする対象は別オブジェクトなので。。。 removeするたびに各Hashをチェックしてremoveするメソッドを別に作ることでも実現できるかもとは思っていますが、あまりスマートじゃないように思うのです。 上のような方法しかないでしょうか?? 他に良い方法があれば教えていただけないでしょうか。よろしくお願いします。 @Override public void saveObject(ObjectDto objectDto) { Object object = objectDto.object; objectDao.saveOrUpdate(object); // DB登録済みのObjectHogesのHogeを削除用リストとしてセットしておく HashSet<Long> delHogeIdSet =null; delHogeIdSet = objectHogeDao.geHogeIdSetByObjectId(object.getObjectId()); // ObjectのHogeSetからセットすべきのHoge一覧を取得する List<HogeSetHoge> hogeSetHogeList = hogeSetHogeDao.loadByHogeSet(object.getHogeSet().getHogeSetId()); // 追加用Hogeリストをセットしておく HashSet<Long> addHogeIdSet =null; addHogeIdSet = hogeSetHogeDao.getHogeIdSetByHogeSetId(object.getHogeSet().getHogeSetId()); if(object.getObjectHoges() != null){ // ユーザのHogeを順にチェック for(ObjectHoge objectHoge : object.getObjectHoges()){ // セットすべきHoge一覧と比較 for(HogeSetHoge hogeSetHoge : hogeSetHogeList){ // ユーザのHogeと登録が必要なHogeを比較 if(hogeSetHoge.getHoge().getHogeId() == objectHoge.getHoge().getHogeId()){ // dbに登録されている場合は削除リストならびに追加リストからはずす delHogeIdSet.remove(hogeSetHoge.getHoge().getHogeId()); addHogeIdSet.remove(hogeSetHoge.getHoge().getHogeId()); } } } // delObjectHogeListをDBから削除する if(delHogeIdSet.size() > 0){ for (Long hogeId : delHogeIdSet){ // objectHogeDao.deleteByHogeId(hogeId,object.getObjectId()); } } // addHogeIdSetをDBに追加する if(addHogeIdSet.size() > 0){ for (Long hogeId : delHogeIdSet){ ObjectHoge objectHoge = new ObjectHoge(); objectHoge.setObject(object); Hoge hoge = hogeDao.findById(Hoge.class, hogeId); objectHoge.setHoge(hoge); objectHogeDao.saveOrUpdate(objectHoge); } } }

    • ベストアンサー
    • Java
  • Javaのプログラムの質問です。

    Javaのプログラムについての質問です。 Listインターフェースの実装クラスの自作と、作成したクラスの全メソッドを呼び出すサンプルを作成せよ、という問題です。  注意点として、java.util.Listの実装クラスは使用出来ません(ArrayListなど)。実装するメソッドは、コードの中に番号を振ってあります。 import java.util.Collection; import java.util.Iterator; import java.util.ListIterator; import java.util.List; class LocalList implements List{  private int Count;  private String Data[];  private Iterator ite;  private ListIterator lite;  // コンストラクタ  void mylist(){   Data = new String[10];   Count = 0;  }  (1)  public boolean add(Object str){   if(Count >= 10){    return false;   }   Data[Count ++] = new String((String)str);   return true;  }  public void add(int i,Object str){  }        public boolean addAll(Collection c){   return false;  }        public boolean addAll(int i,Collection c){   return false;  }    (2)  public void clear(){   Count = 0;  }  public boolean contains(Object str){   return false;  }          public boolean containsAll(Collection c){   return false;  }  public boolean equals(Object str){   return false;  }    (3)  public Object get(int i){   return (i >= Count);  }  public int hashCode(){   return -1;  }  public int indexOf(Object str){   return -1;  }  public boolean isEmpty(){   return false;  }  public Iterator iterator(){   return ite;  }     public int lastIndexOf(Object str){   return -1;  }     public ListIterator listIterator(){   return lite;  }     public ListIterator listIterator(int i){   return lite;  }    (4)  public Object remove(int i){   return (i >= Count);  }    public boolean remove(Object str){   return true;  }         public boolean removeAll(Collection c){   return false;  }         public boolean retainAll(Collection c){   return false;  }    (5)  public Object set(int i,Object str){   return Data[i];  }    (6)  public int size(){   return Count;  }  public List subList(int i,int j){   return this;  }  public Object[] toArray(){   return Data;  }  public Object[] toArray(Object[] a){   return Data;  } } class Main {  public static void main(String[] args) {   mylist sub = new mylist();   sub.add("ビルドバーニングガンダム");   sub.add("ライトニングガンダム");   sub.add("ウイニングガンダム");   sub.add("ガンダムフェニーチェリナーシタ");   sub.add("R・ギャギャ");   for(int i = 0; i < sub.size(); i++){      System.out.println(sub.get(i));   }   // 改行   System.out.println();   // setメソッド   sub.set(1,"ガンダムエピオン");   for(int i = 0; i < sub.size(); i++){    System.out.println(sub.get(i));   }   // 改行   System.out.println();   // sizeメソッド   System.out.println("\r\n" + "機体数は" + sub.size() + "です" + "\r\n");   // removeメソッド   sub.remove(1);   for(int i = 0; i < sub.size(); i++){       System.out.println(sub.get(i));   }   // clearメソッド   sub.clear();   System.out.println("\r\n" + "機体数が" + sub.size() + "になったので負けです");    } } setメソッドとremoveメソッド以外は起動するのようになったのですが、この2つがうんともすんとも動きません。ジェネリクス型を使うという考え方もあるらしいのですが、ネットで調べてもピンと来ず寸詰まり状態になってしまっています。後少しだと思うのですが。。。。 どなたかご教授頂けないでしょうか?よろしくお願い致します。

  • Javaの判定処理について

    いつもお世話になっております。 以下のJavaのコードで、 ☆の部分のif文が何を実施しているのか 分からないのですが、 ご存知の方がいられましたら ご教授をいただけますでしょうか。 【コード】 String value = "あいうえお12345"; int length = value.length(); for (int i = 0; i < length; i++) { char c = value.charAt(i); if ((c & ~0x7f) != 0) { ←☆ 処理1 } }

    • ベストアンサー
    • Java
  • javaについて教えて下さい!

    class SampleA implements Runnable { int tmp1 = 0; int tmp2 = 0; public synchronized void run(){ try{ if(tmp1 == 1){ System.out.print("は"); System.out.print("め"); else if (tmp1 == 2){ System.out.print("じ"); System.out.print("て");          } if(tmp2 == 0) tmp2 = tmp2 + 1; System.out.print("ま"); } System.out.print("。"); }catch(InterrupedException e){ System.out.print("し"); } } } //Sample2.java class Sample2{ public static void main(String[] args){ Sample1 sp = new Sample1(); Thread th1 = new Thread(sp); Thread th2 = new Thread(sp); th1.start(); th2.start(); } } wait(),notify(),throwを使って例外を生じさせるところまではわかったのですが このプログラムを「はじめまして。」と順番に出力するにはどうすればいいですか? プログラム内容は追記する形でお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう