Java中的Iterator支持UnsupportedOperationException

时间:2014-08-15 12:15:32

标签: java

我的模型中有不同的场景,并且在每种情况下,道路网络(图形)的某些路段(边缘)降级(丢失容量)或中断(由于总损坏而移除)。出于这个原因,我试图从原始网络开始迭代每个场景的一组边缘,并通过改变某些边缘的容量并删除其他边缘来更新网络。在开始时,我没有使用迭代器迭代边缘,导致“ConcurrentModificationException”。然后我更改了代码以便使用Iterator,但这次它不允许我使用remove方法和我的迭代器(edgeIt.remove())。我该如何解决这个问题?感谢您的帮助。

.....

ArrayList<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>> FWS = new ArrayList<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>>();
        for(int w=0; w<numOfScenarios; w++){
            FWS.add(w, fr.readData(fileName));
        }

....

//Road Network and Shelters after disruption in Scenarios
        for(int i=1; i<6; i++){
            Iterator<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>> it = FWS.iterator();
            while(it.hasNext()){
                FloydWarshallShortestPaths<Integer, DefaultWeightedEdge> FWIt = it.next();
                Iterator<DefaultWeightedEdge> edgeIt = FWIt.getGraph().edgeSet().iterator();
                while(edgeIt.hasNext()){
                DefaultWeightedEdge e = edgeIt.next();
                    if(arcRiskZoneIndex[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]==i){
                        if(rng.nextDouble()<=arcDisruptProb[FWS.indexOf(FWIt)][i-1]){
                            roadCapS[FWS.get(FWS.indexOf(FWIt)).getGraph().getEdgeSource(e)][FWS.get(FWS.indexOf(FWIt)).getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]=(roadCap[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)]*10000-rng.nextInt(((int) (10000*roadCap[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)]/2000))+1)*2000)/10000;
                            if(roadCapS[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]==0.0){
                                **edgeIt.remove()**;
                            }
                        }
                    }
                }
                for(int s:setOfFacilityNodesDummy){
                    if(shelterRiskZoneIndex[s][FWS.indexOf(FWIt)]==i){
                        if(rng.nextDouble()<=shelterDisruptProb[FWS.indexOf(FWIt)][i-1]){
                            setOfFacilityNodesS.get(FWS.indexOf(FWIt)).remove(s);
                        }
                    }
                }
            }
        }

2 个答案:

答案 0 :(得分:2)

Collection返回的edgeSet()很可能根本不支持remove()操作,或支持remove(),但Iterator支持ConcurrentModificationException没有。

要解决此问题(以及Set),您必须在单独的{{1}}中收集要删除的边缘,并在完成迭代后删除他们通过图表的适当API。

答案 1 :(得分:1)

好的,我做了一些谷歌搜索,显然你正在使用JGraphT库。 (Protip:在你的问题中指明这一点很有帮助!) JavaDoc for Graph.edgeSet()说:

  

返回此图中包含的一组边。该套装备受支持   通过图表,对图表的更改将反映在集合中。如果   当集合上的迭代正在进行时,图形被修改   迭代结果未定义。

现在,这只是意味着如果Graph的边缘发生变化,那么可以在返回的Set中看到这些变化。不幸的是,它没有说明返回Set的更改,导致Graph边缘的更改。鉴于您正在获得UnsupportedOperationException,我假设 Graph不允许您更改返回的SetThe source code of AbstractBaseGraph证实了这一假设:

/**
 * @see Graph#edgeSet()
 */
public Set<E> edgeSet()
{
    if (unmodifiableEdgeSet == null) {
        unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet());
    }

    return unmodifiableEdgeSet;
}

edgeSet()会返回Graph边缘的无法修改的视图。您无法直接更改edgeSet,您必须使用{ {1}}添加/更改/删除边缘的界面。此外,如果您在进行这些更改时迭代Graph,则可能会遇到未定义的行为。

要解决这个问题,我建议首先在迭代时收集要删除的边,然后再删除它们:

edgeSet