使用Java,我有一个要检查的列表,如果通过循环检索的一个子列表满足某些条件,它必须在运行中被替换,因为在下一个循环中我必须在更改的列表上重复该算法。要替换的子列表和要添加的子列表当然可以有不同的长度。
我使用的是ListIterator,因为使用普通的List方法添加和删除不能保证结果。但即使在这里,在main for循环中的第一个for循环(在第二次迭代)的开头抛出一个ConcurrentModificationException,我真的不能想到另一种执行算法的方法。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
public class Dummy {
public static void main(String[] args) {
List<String> nodes = new ArrayList<>(Arrays.asList(
"1", "2", "3", "4", "5", "6", "7"));
ListIterator<String> nodesIterator = nodes.listIterator();
while (nodesIterator.hasNext()) {
nodesIterator.next();
List<String> nodesToCheck = nodes.subList(nodesIterator
.previousIndex(),
nodesIterator.previousIndex() + 3);
if (nodesToCheck.equals(Arrays.asList("3", "4", "5"))) {
List<String> nodesToReplace = new ArrayList<String>(
Arrays.asList("11", "11", "00", "11"));
for (String n : nodesToCheck) {
//ConcurrentModificationException thrown here at
// beginning of second iteration
nodesIterator.remove();
nodesIterator.next();
}
for (String n : nodesToReplace) {
nodesIterator.add(n);
}
}
}
}
}
非常感谢任何帮助,谢谢;)
答案 0 :(得分:3)
您正在修改初始节点列表,因此抛出异常是很自然的。您应该遍历节点列表的副本。
这是一个可运行的例子,它可以重现问题(我在OP编辑之前编写过):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
int number = 2;
List<String> nodes = new ArrayList<>(Arrays.asList("Hello",
"World!", "How", "Are", "You"));
ListIterator<String> nodesIterator = nodes.listIterator();
while (nodesIterator.hasNext()) {
nodesIterator.next();
int fromIndex = nodesIterator.previousIndex();
List<String> nodesToCheck = nodes.subList(fromIndex,fromIndex + number);
if (nodesToCheck.contains("Hello")) {
for (String n : nodesToCheck) { //ConcurrentModificationException
// thrown here at beginning of second iteration
nodesIterator.remove();
nodesIterator.next();
}
List<String> nodesToReplace = new ArrayList<>(
Arrays.asList("replace"));
for (String n : nodesToReplace) {
nodesIterator.add(n);
}
}
}
}
}
快速而肮脏的修补方法(在更复杂的设计中可能是必要的)是:
public class Main {
public static void main(String[] args) {
int number = 2;
List<String> nodes = new ArrayList<>(Arrays.asList("Hello", "World!",
"How", "Are", "You"));
boolean change = true;
while (change) {
List<String> copy = new ArrayList<>(nodes);
ListIterator<String> nodesIterator = copy.listIterator();
while (nodesIterator.hasNext()) {
nodesIterator.next();
int fromIndex = nodesIterator.previousIndex();
List<String> nodesToCheck = nodes.subList(fromIndex, Math.min
(fromIndex + number, nodes.size()));
if ((nodesToCheck.equals(Arrays.asList("How", "Are")) ||
nodesToCheck.equals(Arrays.asList("Hello", "World!")))) {
for (String n : nodesToCheck) {
//ConcurrentModificationException thrown here
// at beginning of second iteration
nodesIterator.remove();
if (nodesIterator.hasNext()) {
nodesIterator.next();
}
}
nodesIterator.previous();
List<String> nodesToReplace = new ArrayList<>(Arrays.asList
("replace"));
for (String n : nodesToReplace) {
nodesIterator.add(n);
}
nodes = copy;
change = true;
break;
} else change = false;
}
}
System.out.println(Arrays.toString(nodes.toArray()));
}
}
虽然可以进一步简化。然而,对于这些问题,这是一种通用的编程方法 - 虽然有一些变化通过集合重新运行并修改,直到没有变化。