Java 删除重复项linkedlist并发修改异常

Java 删除重复项linkedlist并发修改异常,java,Java,我有一个linkedlist,其中每个元素都有key和valueArrayList。我想合并具有相同键的元素 Iterator<CElem> oItr = linkedList.iterator(); { while (oItr.hasNext()) { CElem outer = oItr.next(); Iterator<CElem> iItr

我有一个linkedlist,其中每个元素都有key和valueArrayList。我想合并具有相同键的元素

    Iterator<CElem> oItr = linkedList.iterator();
    {
        while (oItr.hasNext())
        {
            CElem outer = oItr.next();              
            Iterator<CElem> iItr = linkedList.iterator();
            {
                while (iItr.hasNext())
                {
                    CElem inner = iItr.next();
                    if (outer.equals(inner))
                        continue;

                    if (outer.getKey().equals(inner.getKey()))
                    {
                        outer.getValues().addAll(inner.getValues());
                        iItr.remove();
                    }
                }
            }
        }
    }

虽然我正在使用迭代器删除方法,但得到了java.util.ConcurrentModificationException。应该改变什么来摆脱这个问题

两个迭代器都在遍历链表

Iterator<CElem> oItr = linkedList.iterator();
....
Iterator<CElem> iItr = linkedList.iterator();
也许iItr应该用于内部数组列表

更新上面的答案我误读了这个问题。然而,挑战在于有两个迭代器遍历列表,因此当您使用一个迭代器的remove方法时,另一个迭代器仍然检测并发修改

通常,要从列表中删除重复项,您可以通过一个集合(例如哈希集合)运行它们,但这对您不起作用,因为这只是密钥复制,而不是列表的整个成员


我会采取一种方法,尝试在一个单独的列表中查找并捕获重复的键及其值,然后作为单独的步骤合并并删除重复项。

您的两个迭代器都在遍历链接列表

Iterator<CElem> oItr = linkedList.iterator();
....
Iterator<CElem> iItr = linkedList.iterator();
也许iItr应该用于内部数组列表

更新上面的答案我误读了这个问题。然而,挑战在于有两个迭代器遍历列表,因此当您使用一个迭代器的remove方法时,另一个迭代器仍然检测并发修改

通常,要从列表中删除重复项,您可以通过一个集合(例如哈希集合)运行它们,但这对您不起作用,因为这只是密钥复制,而不是列表的整个成员


我会采取一种方法,尝试在一个单独的列表中查找并捕获重复的键及其值,然后作为单独的步骤合并并删除重复项。

您使用一个迭代器删除元素,因此第二个迭代器不知道此删除操作,并引发ConcurrentModificationException

顺便说一句:


您应该考虑使用具有关键字值对的列表(

),用一个迭代器删除元素,因此第二个不知道这个移除,而CONTRONTRONMODIGATIORATION异常被抛出

顺便说一句:


你应该考虑使用具有关键字值对的列表[/p>< p>代替]问题是,当使用IIT.Enter时,它修改了列表,IITR很高兴,因为它知道改变了什么,但是OITR不是。我可以看到三种可能的解决方案:

切换到并发列表,例如ConcurrentLinkedQueue-但有关此警告,请参阅中的答案 切换到集合结构,例如TreeSet,它将自动保持项目的唯一性,但不会保留其顺序 确保从其中一个迭代器中删除后不使用其他迭代器-可以通过切换要删除的元素来实现,即将iItr.remove更改为:


这将导致删除每个键的第一个实例,而不是后续的实例,这可能不是您想要的行为-在这种情况下,您可以尝试向后迭代列表。

问题是,当您使用iItr.remove时,它会修改列表,iItr很满意,因为它知道发生了什么变化,但oItr并非如此。我可以看到三种可能的解决方案:

切换到并发列表,例如ConcurrentLinkedQueue-但有关此警告,请参阅中的答案 切换到集合结构,例如TreeSet,它将自动保持项目的唯一性,但不会保留其顺序 确保从其中一个迭代器中删除后不使用其他迭代器-可以通过切换要删除的元素来实现,即将iItr.remove更改为:


这将导致删除每个键的第一个实例,而不是后续的实例,这可能不是您想要的行为-在这种情况下,您可以尝试向后迭代列表。

在另一个列表中添加要删除的元素,然后在该列表的末尾循环以删除这些元素


或者,使用映射/集合。

在另一个列表中添加要删除的元素,然后在该列表末尾循环以删除这些元素

或者,使用地图/集合。

这行吗

 Iterator<CElem> oItr = linkedList.iterator();
    {
        while (oItr.hasNext())
        {
            CElem outer = oItr.next();              
            Iterator<CElem> iItr = linkedList.iterator();
            {
                while (iItr.hasNext())
                {
                    CElem inner = iItr.next();
                    if (outer.equals(inner))
                        continue;

                    if (outer.getKey().equals(inner.getKey()))
                    {
                        inner.getValues().addAll(outer.getValues());
                        outer.remove();
                        break;
                    }
                }
            }
        }
    }
这样行吗

 Iterator<CElem> oItr = linkedList.iterator();
    {
        while (oItr.hasNext())
        {
            CElem outer = oItr.next();              
            Iterator<CElem> iItr = linkedList.iterator();
            {
                while (iItr.hasNext())
                {
                    CElem inner = iItr.next();
                    if (outer.equals(inner))
                        continue;

                    if (outer.getKey().equals(inner.getKey()))
                    {
                        inner.getValues().addAll(outer.getValues());
                        outer.remove();
                        break;
                    }
                }
            }
        }
    }

为什么不使用LinkedHashSet?尊敬的,我不同意@JunedAhsan的可能副本。vjk正在使用Iterator.remove,他的情况更复杂。更接近于此:@Taylor同意,这就是为什么使用“可能”而不是“精确”-为什么不使用LinkedHashSet?尊敬的,我不同意@JunedAhsan的可能副本。vjk正在使用Iterator.remove,他的情况更复杂。更接近于此:@Taylor同意,这就是为什么使用“可能”而不是“精确”-