操作セットからjavaを投げ出す.lang.IllegalStateException異常の原因とその解決構想


詳細
Javaではコンテナクラスがよく使用され、反復器クラスIteratorによってコレクション内の要素を反復することで、個々の要素ごとに次のような操作を行うことができます.
集合内の条件を満たさない要素を削除するには、Iteratorで削除するには、まずnextメソッドを使用して集合内の要素を反復し、removeメソッドを呼び出すだけです.しかし、プログラム中にうっかりして、1回のnextメソッドに対して1つの要素を反復し、1回以上のremove削除操作を実行するとjavaが報告される.lang.IllegalStateException異常.
実は、理由は明らかで、反復は一度に集合の中の1つの要素しか反復できないが、その反復に対して何度も削除を実行すると、明らかに集合状態の異常な問題をもたらし、異常を投げ出す.
例を挙げて説明します.
集合のフィルタリング機能を実現する方法があります.コードは次のとおりです.
public void filter(Collection container, Map parametersMap) {
  
   this.setFilter(parametersMap);
  
   Iterator it = container.iterator();
   while(it.hasNext()) {
    String s = it.next().trim();
    Iterator>,Interval>> mapIt = this.hitStageConditionsMap.entrySet().iterator();
    while(mapIt.hasNext()) {
     Map.Entry>,Interval> entry = mapIt.next();
     List> key = entry.getKey();
     Interval interval = entry.getValue();
     //     , s         
     if(!this.passOneCondition(s, key, interval)) { //        
     it.remove();
     }
    }
   }  
}

プログラム設計の本意は:
container集合の要素を反復する過程で、まずit.next()は文字列を反復し,mapItの中には条件Mapの反復器インスタンスがあり,条件が多重であるため反復器を使用する必要がある.これを呼び出すとpassOneCondition(s,key,interval)がいずれかの条件を満たさないと判断した場合、集合containerで対応するit反復文字列を削除し、他のフィルタを行わない条件でフィルタを実行しなくなった.
上の方法でjavaを投げ出します.lang.IllegalStateException異常:
java.lang.IllegalStateException
at java.util.HashMap$HashIterator.remove(Unknown Source)
at org.shirdrn.filter.collection.HitStageFilter.filter(HitStageFilter.java:45)
at org.shirdrn.filter.collection.TestHitStageFilter.testHitStageFilter(TestHitStageFilter.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:230)
at junit.framework.TestSuite.run(TestSuite.java:225)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

container集合の要素を反復する過程で、まずitを通過するからである.next()は文字列を反復し、mapItの中には条件Mapの反復器のインスタンスがあり、thisが呼び出される.passOneCondition(s,key,interval)がいずれかの条件を満たさないと判断した場合,集合containerで対応するit反復文字列を削除する.条件Mapの反復を終了するためにbreakを実行しないと、removeコレクションcontainerを複数回削除してitを実行する.next()は反復する文字列なのでjavaを投げ出す.lang.IllegalStateException異常.したがって、コレクション反復操作を実行するときは、removeを実行した後にbreakを追加する方法に注意してください.文でいいです.
public void filter(Collection container, Map parametersMap) {
  
   this.setFilter(parametersMap);
  
   Iterator it = container.iterator();
   while(it.hasNext()) {
    String s = it.next().trim();
    Iterator>,Interval>> mapIt = this.hitStageConditionsMap.entrySet().iterator();
    while(mapIt.hasNext()) {
     Map.Entry>,Interval> entry = mapIt.next();
     List> key = entry.getKey();
     Interval interval = entry.getValue();
     //     , s         
     if(!this.passOneCondition(s, key, interval)) { //        
     it.remove();
     break;
     }
    }
   }  
}