操作集合拋出java.lang.IllegalStateException異常的原因及其解決思路

在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;
}
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章