`

操作集合抛出java.lang.IllegalStateException异常的原因及其解决思路

    博客分类:
  • java
阅读更多
在Java中经常用到容器类,可以通过迭代器类Iterator来对集合中的元素进行迭代,从而对每个单独的元素进行某种操作,例如:

要删除集合中某一个不满足条件的元素,通过Iterator来删除,首先需要使用next方法迭代出集合中的元素,然后只需要调用remove方法即可。但是如果程序中不小心,造成对一次next方法执行迭代出一个元素,而执行了多于一次的remove删除操作,就会报java.lang.IllegalStateException异常。

其实,原因很显然了,迭代一次只能迭代出集合中的一个元素,而对该一次迭代执行了多次删除,显然就造成集合状态的不正常问题,抛出异常。

下面举一个例子说明一下。

有一个方法实现对集合的过滤功能,代码如下所示:

public void filter(Collection<String> container, Map<Integer, Object> parametersMap) {
  
   this.setFilter(parametersMap);
  
   Iterator<String> it = container.iterator();
   while(it.hasNext()) {
    String s = it.next().trim();
    Iterator<Map.Entry<List<Map<Integer,String>>,Interval<Integer, Integer>>> mapIt = this.hitStageConditionsMap.entrySet().iterator();
    while(mapIt.hasNext()) {
     Map.Entry<List<Map<Integer,String>>,Interval<Integer, Integer>> entry = mapIt.next();
     List<Map<Integer,String>> key = entry.getKey();
     Interval<Integer, Integer> interval = entry.getValue();
     // 调用方法,对s进行一个条件的过滤
     if(!this.passOneCondition(s, key, interval)) { // 如果不满足条件
     it.remove();
     }
    }
   }  
}


程序设计的本意是:

迭代container集合中元素的过程中,首先通过it.next()迭代出一个字符串,然后mapIt里面是条件Map的迭代器实例,由于条件是多重的,需要使用迭代器。当调用this.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迭代出的字符串。如果我们不执行break来终止条件Map的迭代,就会出现多次删除remove集合container中执行一次it.next()迭代出的字符串,所以抛出java.lang.IllegalStateException异常。 所以,在执行集合迭代操作过程中要谨慎小心,上面方法在执行完成remove之后,添加一个break;语句就行了:

public void filter(Collection<String> container, Map<Integer, Object> parametersMap) {
  
   this.setFilter(parametersMap);
  
   Iterator<String> it = container.iterator();
   while(it.hasNext()) {
    String s = it.next().trim();
    Iterator<Map.Entry<List<Map<Integer,String>>,Interval<Integer, Integer>>> mapIt = this.hitStageConditionsMap.entrySet().iterator();
    while(mapIt.hasNext()) {
     Map.Entry<List<Map<Integer,String>>,Interval<Integer, Integer>> entry = mapIt.next();
     List<Map<Integer,String>> key = entry.getKey();
     Interval<Integer, Integer> interval = entry.getValue();
     // 调用方法,对s进行一个条件的过滤
     if(!this.passOneCondition(s, key, interval)) { // 如果不满足条件
     it.remove();
     break;
     }
    }
   }  
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics