Java:迭代迭代时更改可迭代对象的属性

时间:2009-10-25 21:13:22

标签: java iteration set

以下代码仅用于生成问题示例:

 public static void main(String[] args) {
  Collection<Integer> src = new ArrayList<Integer>();
  Collection<Integer> dest = new ArrayList<Integer>();

  src.add(2);
  src.add(7);
  src.add(3);
  src.add(2201);
  src.add(-21);

  dest.add(10);

  while (src.size() != 0) {
   for (int i : dest) {
    int min = Collections.min(src);
    dest.add(min);
    src.remove(min);
   }
  }

 }

我想要做的是按照特定的顺序将所有内容从src移动到dest。 (这里,它是什么是最小值,但这只是我真正问题的简化。)但是,我在迭代它时修改dest,并得到以下错误:

Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
 at java.util.AbstractList$Itr.next(Unknown Source)
 at nth23.experimental.MoveBetweenSets.main(MoveBetweenSets.java:25)

我怎样才能解决这个问题?

6 个答案:

答案 0 :(得分:2)

您是否有理由不能将源列表复制到目标列表然后对其进行排序?

Collection<Integer> dest = new ArrayList<Integer>(src);
Collections.sort(dest);

答案 1 :(得分:2)

这是一种解决方法:

while (!src.isEmpty()) {
    int min = Collections.min(src);
    dest.add(min);
    src.remove(min);
}

但这可能会让事情变得更糟。更具体一点(如Jon所说)。

答案 2 :(得分:1)

您可以使用iterator.remove()在对其进行迭代时从集合中删除(以及某些集合),但通常无法添加

但是,正如newacct在评论中指出的那样,ListIterator界面 包含add方法,因此您应该能够像这样更改代码:

public static void main(String[] args) {
  Collection<Integer> src = new ArrayList<Integer>();
  List<Integer> dest = new ArrayList<Integer>();

  src.add(2);
  src.add(7);
  src.add(3);
  src.add(2201);
  src.add(-21);

  dest.add(10);

  while (src.size() != 0) {
   for (ListIterator<Integer> li = dest.listIterator(); li.hasNext() ;) {
    int min = Collections.min(src);
    li.add(min);
    src.remove(min);
   }
  } 
 }

请注意,现在必须将dest声明为List而不是Collection,并且需要显式扩展for循环。但是,我仍然不确定你为什么要首先迭代dest。你在每次迭代时都添加了一个元素,所以你永远不会到达终点。

这有什么问题?

  while (src.size() != 0) {
    int min = Collections.min(src);
    dest.add(min);
    src.remove(min);
  } 

或者,正如其他人所说,只需致电sort() - 如果需要,可以传递自定义Comparator

答案 3 :(得分:1)

老实说,我没有得到for (int i : dest)部分。如果你删除它,实际上没有问题,这回答了问题:)

答案 4 :(得分:0)

正如您所见,您在迭代时无法更改集合。 (更确切地说,你可以改变它,但你不能继续迭代)

您可以迭代列表副本或使用传统的for循环。

无论哪种方式,确保在修改集合时准确理解索引会发生什么;否则,您的代码将无法正常工作。

有关更具体的建议,请告诉我们您的实际行动。

答案 5 :(得分:0)

您可以创建临时列表,在其中跟踪应添加和删除的内容,而无需实际更改dest和src。然后,在循环外部使用临时列表添加和删除必要的项目。 但就像Jon Skeet所说,更具体的要求会有所帮助。我认为有一些限制。