Java:在这种特殊情况下,如何处理ConcurrentModificationException?

Java:在这种特殊情况下,如何处理ConcurrentModificationException?,java,exception,arraylist,Java,Exception,Arraylist,在我发布这个问题之前,我阅读了中的帖子。但对于这个特殊的问题,我真的不知道如何应用同样的哲学 在下面的问题中,我的变量graph具有以下结构:HashMap。 和u和v具有类型int。基本上,我想删除数组列表中键值为I的值v,其中I出现在v的数组列表中 因此,如果整数i出现在v的arraylist中,我们在图中获得i的arraylist,并从中删除值v 这听起来很复杂。但我现在被这个ConcurrentModificationException困扰了一段时间 public int random_

在我发布这个问题之前,我阅读了中的帖子。但对于这个特殊的问题,我真的不知道如何应用同样的哲学

在下面的问题中,我的变量
graph
具有以下结构:
HashMap
。 和
u
v
具有类型
int
。基本上,我想删除数组列表中键值为
I
的值
v
,其中
I
出现在
v
的数组列表中

因此,如果整数
i
出现在
v
的arraylist中,我们在图中获得
i
的arraylist,并从中删除值
v

这听起来很复杂。但我现在被这个ConcurrentModificationException困扰了一段时间

public int random_contraction_algo(){
    while(graph.size() > 2){
        int u = select_remaining_edges_at_random(new ArrayList<Integer> (graph.keySet()));
        int v = select_remaining_edges_at_random(graph.get(u));      
        merge(u,v);        
    }
    return -1;
}

// select a pair of vertices from an edge
public int select_remaining_edges_at_random(ArrayList<Integer> vertices){
    int index = (int)(Math.random() * (vertices.size()));
    return vertices.get(index);
}

public void merge(int u, int v){

    graph.get(u).addAll(graph.get(v));

    // remove self-loops
    graph.get(u).removeAll(Collections.singleton(u));
    graph.get(u).removeAll(Collections.singleton(v));

    // make sure all the edges of v are connected to u instead v
    for(Iterator<Integer> iterator = graph.get(v).iterator(); iterator.hasNext();){
        Integer i = iterator.next();
        graph.get(i).remove((Integer) v);
        graph.get(i).add(u);

    }
    // remove key
      graph.remove(v);
}

从循环之前的列表中明确删除
v
graph.get(v)。删除(v)

List=graph.get(v);
列表。删除(v);
for(整数i:列表){
图.获取(i).删除(v)
}

从循环前的列表中明确删除
v
graph.get(v).Remove(v)

List=graph.get(v);
列表。删除(v);
for(整数i:列表){
图.获取(i).删除(v)
}

问题在于当
v==i
时,您正在修改与迭代相同的列表

一个简单的解决方案是防范这种情况:

for(Iterator<Integer> it = graph.get(v).iterator(); it.hasNext();) {
    Integer i = it.next();
    if (i == v) {
        it.remove();
    } else {
        graph.get(i).remove((Integer) v);
    }
}
for(Iterator it=graph.get(v.Iterator();it.hasNext();){
整数i=it.next();
如果(i==v){
it.remove();
}否则{
graph.get(i).remove((整数)v);
}
}

问题在于当
v==i
时,您正在修改与迭代相同的列表

一个简单的解决方案是防范这种情况:

for(Iterator<Integer> it = graph.get(v).iterator(); it.hasNext();) {
    Integer i = it.next();
    if (i == v) {
        it.remove();
    } else {
        graph.get(i).remove((Integer) v);
    }
}
for(Iterator it=graph.get(v.Iterator();it.hasNext();){
整数i=it.next();
如果(i==v){
it.remove();
}否则{
graph.get(i).remove((整数)v);
}
}

我可能误解了你的意思。但是如果你不同意的话

因此,如果整数i出现在v的arraylist中,我们得到图中i的arraylist,并从中移除值v

这就是你想做的吗

HashMap<Integer, ArrayList<Integer>> graph = new HashMap<Integer, ArrayList<Integer>>();
for (int i = 0; i < 100; i++) {
    graph.put(i, new ArrayList<Integer>());
}

int i = 0; // change value to whatever
int v = 0; // change value to whatever
if (graph.get(v).contains(i)) {
    graph.get(i).remove(new Integer(v));
}
HashMap graph=newhashmap();
对于(int i=0;i<100;i++){
put(i,newarraylist());
}
int i=0;//将值更改为任意值
int v=0;//将值更改为任意值
if(图get(v)包含(i)){
graph.get(i).remove(新整数(v));
}
如果不是,你可以试着解释清楚你需要什么

编辑:

我认为这应该奏效:

HashMap<Integer, ArrayList<Integer>> graph = new HashMap<Integer, ArrayList<Integer>>();
for (int i = 0; i < 100; i++) {
    graph.put(i, new ArrayList<Integer>());
}

int v = 0; // change value to whatever
int u = 0;
ArrayList<Integer> list = new ArrayList<Integer>(graph.get(v));
for(Integer i : list){
    if(graph.get(i).contains(v)){
        graph.get(i).remove(new Integer(v));
        graph.get(i).add(u);
    }
}
HashMap graph=newhashmap();
对于(int i=0;i<100;i++){
put(i,newarraylist());
}
int v=0;//将值更改为任意值
int u=0;
ArrayList=newArrayList(graph.get(v));
for(整数i:列表){
if(图get(i)包含(v)){
graph.get(i).remove(新整数(v));
图.get(i).add(u);
}
}
这将创建所讨论的
ArrayList
的副本,因此我们从不在地图上迭代,从而可以对地图进行编辑


告诉我它是否有效。

我可能误解了你的意思。但是如果你不同意的话

因此,如果整数i出现在v的arraylist中,我们得到图中i的arraylist,并从中移除值v

这就是你想做的吗

HashMap<Integer, ArrayList<Integer>> graph = new HashMap<Integer, ArrayList<Integer>>();
for (int i = 0; i < 100; i++) {
    graph.put(i, new ArrayList<Integer>());
}

int i = 0; // change value to whatever
int v = 0; // change value to whatever
if (graph.get(v).contains(i)) {
    graph.get(i).remove(new Integer(v));
}
HashMap graph=newhashmap();
对于(int i=0;i<100;i++){
put(i,newarraylist());
}
int i=0;//将值更改为任意值
int v=0;//将值更改为任意值
if(图get(v)包含(i)){
graph.get(i).remove(新整数(v));
}
如果不是,你可以试着解释清楚你需要什么

编辑:

我认为这应该奏效:

HashMap<Integer, ArrayList<Integer>> graph = new HashMap<Integer, ArrayList<Integer>>();
for (int i = 0; i < 100; i++) {
    graph.put(i, new ArrayList<Integer>());
}

int v = 0; // change value to whatever
int u = 0;
ArrayList<Integer> list = new ArrayList<Integer>(graph.get(v));
for(Integer i : list){
    if(graph.get(i).contains(v)){
        graph.get(i).remove(new Integer(v));
        graph.get(i).add(u);
    }
}
HashMap graph=newhashmap();
对于(int i=0;i<100;i++){
put(i,newarraylist());
}
int v=0;//将值更改为任意值
int u=0;
ArrayList=newArrayList(graph.get(v));
for(整数i:列表){
if(图get(i)包含(v)){
graph.get(i).remove(新整数(v));
图.get(i).add(u);
}
}
这将创建所讨论的
ArrayList
的副本,因此我们从不在地图上迭代,从而可以对地图进行编辑


告诉我它是否有效。

我认为这不会是一个问题,除非I==v,但是你可以使用标准迭代器方法。你能给我一个例子吗?修改循环中的其他列表不会是一个问题。如果下面两种解决方案中的任何一种仍然出现异常,那么它是由您的帖子中未包含的某些代码引起的@Ordous的解决方案也可能失败,如果您将相同的列表存储在地图中的不同键下。我的问题对此免疫(但效率稍低,因为它需要对列表进行一次附加扫描)。我将再次编辑这个问题,因为我想向你们展示更多的代码,这涉及到一个外部循环。请看UPDATE@mynameisJEFF您是否有可能给出一个失败的小数据示例?比如2-3个有边的节点?我已经尝试了3个节点,每个节点都相互连接,效果很好(如果没有显式的自循环移除,则会引发异常)。我认为这不会是问题,除非I==v,但是您可以使用标准迭代器方法。您能给我举个例子吗?修改循环中的其他列表不会是问题。如果下面两种解决方案中的任何一种仍然出现异常,那么它是由您的帖子中未包含的某些代码引起的@Ordous的解决方案也可能失败,如果您将相同的列表存储在地图中的不同键下。我的问题对此免疫(但效率稍低,因为它需要对列表进行一次附加扫描)。我将再次编辑这个问题,因为我想向你们展示更多的代码,这涉及到一个外部循环。请看UPDATE@mynameisJEFF你有没有可能给出一个小数据表