【问题标题】:removing duplicates linkedlist concurrent modification exception删除重复链表并发修改异常
【发布时间】:2013-08-13 16:41:05
【问题描述】:

我有一个链表,其中每个元素都有键和值(ArrayList<dataStructure>)。我想合并具有相同键的元素。

    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。应该改变什么来摆脱这个。

【问题讨论】:

标签: java


【解决方案1】:

您使用其中一个迭代器删除元素,因此第二个迭代器不知道此删除并抛出ConcurrentModificationException

顺便说一句:

您应该考虑使用some multimap 代替具有键值对的列表

【讨论】:

    【解决方案2】:

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

    或者,使用地图/集合。

    【讨论】:

      【解决方案3】:

      你的两个迭代器都在遍历链表

      Iterator<CElem> oItr = linkedList.iterator();
      ....
      Iterator<CElem> iItr = linkedList.iterator();
      

      可能 iItr 应该用于内部数组列表?

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

      通常,要从列表中删除重复项,您可以通过 Set(例如 HashSet)运行它们,但这对您不起作用,因为它只是键重复,而不是列表的整个成员。

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

      【讨论】:

        【解决方案4】:

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

        1. 切换到并发列表(例如ConcurrentLinkedQueue - 但请参阅Lock-Free Concurrent Linked List in Java 的答案以获取有关此问题的警告)
        2. 切换到一组结构,例如TreeSet,这将使您的商品自动保持唯一(但不会保留它们的顺序)
        3. 确保从其中一个迭代器中删除后不使用另一个迭代器 - 您可以通过切换要删除的元素来做到这一点,即将 iItr.remove() 更改为:

           oItr.remove();
           break;
          

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

        【讨论】:

          【解决方案5】:

          这行得通吗?

           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;
                              }
                          }
                      }
                  }
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-03-24
            • 1970-01-01
            • 2012-10-29
            • 1970-01-01
            • 1970-01-01
            • 2014-09-02
            • 2016-11-19
            相关资源
            最近更新 更多