我试图从给定的边和根构造二叉树。我迭代所有行并将左子节点设置为给定节点(如果找到第二次给定节点则右子节点)。当设置子节点时,我从ArrayList中删除此元素,并在子节点上递归调用函数。
List<Integer[]> edges = new ArrayList<>();
此数组列表例如:
3 4
3 0
4 5
1 3
2 4
和root是1
。
我有类Node
public class Node {
public Node left;
public Node right;
public int key;
public Node(int k) {
key = k;
left = null;
right = null;
}
...}
我构建树的功能是:
public static void edgeToNodes(Node root) {
if (root == null) return;
int count = 0;
for (Iterator<Integer[]> iterator = edges.iterator(); iterator.hasNext(); ) {
Integer[] edge = iterator.next();
for (int i = 0; i < edge.length; i++) {
if (edge[i] == root.key) {
if (count == 0) {
Node left;
if (i == 0) {
left = new Node(edge[1]);
root.setLeft(left);
} else {
left = new Node(edge[0]);
root.setLeft(left);
}
iterator.remove();
count++;
edgeToNodes(left);
} else {
Node right;
if (i == 0) {
right = new Node(edge[1]);
root.setRight(right);
} else {
right = new Node(edge[0]);
root.setRight(right);
}
iterator.remove();
edgeToNodes(right);
}
}
}
}
}
问题是它在java.util.ConcurrentModificationException
和Integer[] edge = iterator.next();
上为edgeToNodes(left);
提供了帮助我如何避免此异常?
答案 0 :(得分:1)
您正在迭代它时从列表中删除元素。
如果只通过一个迭代器来实现它,它会起作用。问题是您使用递归,因此创建几个修改相同列表的迭代器。这会导致ConcurrentModificationException
。
您可以以更迭代的方式构建节点。
pendingNodes
)。pendingNodes
。pendingNodes
。以下是代码示例:
public class Problem {
private List<Integer[]> edges;
private LinkedList<Node> pendingNodes = new LinkedList<>();
private Map<Integer, Node> nodeMap = new HashMap<>();
private Set<Integer> visitedNodes = new HashSet<>();
public Problem(List<Integer[]> edges) {
this.edges = edges;
}
public void run(Integer root) {
//Initialization
Node rootNode = new Node(root);
this.pendingNodes.add(rootNode);
this.nodeMap.put(root, rootNode);
while(!pendingNodes.isEmpty()) {
Node parent = pendingNodes.poll();
for (Integer[] edge : edges) {
if(edge[0].equals(parent.getKey())) {
link(parent, edge[1]);
} else if (edge[1].equals(parent.getKey())) {
link(parent, edge[0]);
}
}
visitedNodes.add(parent.getKey());
}
}
public void link(Node parent, Integer child) {
if(!visitedNodes.contains(child)) {
//get the corresponding node, create it if not exists
Node childNode = nodeMap.get(child);
if (childNode == null) {
childNode = new Node(child);
nodeMap.put(child, childNode);
pendingNodes.add(childNode);
}
//Choose between left and right...
if (parent.getLeft() == null) {
parent.setLeft(childNode);
} else {
parent.setRight(childNode);
}
}
}
public static void main(String[] args) {
//Build the input dataset
List<Integer[]> edges = Arrays.asList(
new Integer[]{3, 4},
new Integer[]{3, 0},
new Integer[]{4, 5},
new Integer[]{1, 3},
new Integer[]{2, 4}
);
Problem problem = new Problem(edges);
problem.run(1);
Map<Integer, Node> nodeMap = problem.nodeMap;
for (Node node : nodeMap.values()) {
System.out.println(node);
}
}
}
输出(我自定义Node#toString()
):
0 => {null, null}
1 => {3, null}
2 => {null, null}
3 => {4, 0}
4 => {5, 2}
5 => {null, null}
答案 1 :(得分:0)
您遇到的问题是每次进行递归时,都会在同一列表上创建一个新的迭代器。迭代器(在某些时候)然后从该列表中删除项目,然后在递归中返回。然而,备份一步你的列表就丢失了一个元素,而你正在迭代它而没有它被迭代器本身删除(它被迭代器从递归线向下一步移除)。
=&GT; ConcurrentModificationException的