gpt4 book ai didi

合并树结构中的节点时出现 java.util.ConcurrentModificationException

转载 作者:行者123 更新时间:2023-12-02 05:33:08 25 4
gpt4 key购买 nike

我想合并同名的节点,并将它们的子节点添加到一起。但我得到了 java.util.ConcurrentModificationException 异常:

Exception in thread "main" java.util.ConcurrentModificationException    
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at test.Test.mergeNode(Test.java:60)
at test.Test.main(Test.java:43)

以下是来源。有人可以给一些提示吗?欢迎任何建议。

public class Test {
public static void main(String[] args) throws Exception {

TreeLayoutNode root = new TreeLayoutNode();
root.setName("Production");

TreeLayoutNode node1 = new TreeLayoutNode();
node1.setName("node1");

TreeLayoutNode node2 = new TreeLayoutNode();
node2.setName("node1");

TreeLayoutNode child1 = new TreeLayoutNode();
child1.setName("child1");

TreeLayoutNode child2 = new TreeLayoutNode();
child2.setName("child2");

TreeLayoutNode child3 = new TreeLayoutNode();
child3.setName("child3");

root.addChildNode(node1);
root.addChildNode(node2);

node1.addChildNode(child1);
node1.addChildNode(child2);

node2.addChildNode(child1);
node2.addChildNode(child3);

HashMap<String, TreeLayoutNode> nodeMap = Maps.newHashMap();
mergeNode(root, nodeMap);

}

/**
*
* @param node
*/
private static void mergeNode(TreeLayoutNode node, HashMap<String, TreeLayoutNode> nodeMap) {
List<TreeLayoutNode> children = node.getChildren();

if(CollectionUtils.isEmpty(children)){
return;
}

Iterator<TreeLayoutNode> it = children.iterator();
while(it.hasNext()){
TreeLayoutNode child = it.next();
if(nodeMap.containsKey(child.getName())){
TreeLayoutNode duplicate = nodeMap.get(child.getName());
List<TreeLayoutNode> childrenOfChild = child.getChildren();
if(CollectionUtils.isNotEmpty(childrenOfChild)){
for(TreeLayoutNode single: childrenOfChild){
duplicate.addChildNode(single);
}
node.removeChildNode(child);
mergeNode(duplicate, nodeMap);
}
}else{
nodeMap.put(child.getName(), child);
}
}
}
}

public class TreeLayoutNode {

private String name;

private String parent;

private Long capacity;

private List<Proportion> proportions;

private List<TreeLayoutNode> children;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getParent() {
return parent;
}

public void setParent(String parent) {
this.parent = parent;
}

public Long getCapacity() {
return capacity;
}

public void setCapacity(Long capacity) {
this.capacity = capacity;
}

public List<Proportion> getProportions() {
return proportions;
}

public void setProportions(List<Proportion> proportions) {
this.proportions = proportions;
}

public List<TreeLayoutNode> getChildren() {
return children;
}

public void setChildren(List<TreeLayoutNode> children) {
this.children = children;
}

public void addChildNode(TreeLayoutNode child) {
if (children == null) {
children = Lists.newArrayList();
}

child.setParent(this.getName());
children.add(child);
}

public void removeChildNode(TreeLayoutNode child){
children.remove(child);
}

public void addProportion(Proportion proportion) {
if (proportions == null) {
proportions = Lists.newArrayList();
}
proportions.add(proportion);
}

public int hashCode() {
return name == null ? 0: name.hashCode();
}

public boolean equals(Object o) {
if (o instanceof TreeLayoutNode) {
TreeLayoutNode target = (TreeLayoutNode) o;
if (this.name == null) {
return target.getName() == null;
} else {
return this.name.equals(target.getName());
}
} else {
return false;
}
}
}

最佳答案

Iterator<TreeLayoutNode> it = children.iterator();
while(it.hasNext()){
TreeLayoutNode child = it.next();
if(nodeMap.containsKey(child.getName())){
TreeLayoutNode duplicate = nodeMap.get(child.getName());
List<TreeLayoutNode> childrenOfChild = child.getChildren();
if(CollectionUtils.isNotEmpty(childrenOfChild)){
for(TreeLayoutNode single: childrenOfChild){
duplicate.addChildNode(single);
}
node.removeChildNode(child);
mergeNode(duplicate, nodeMap);
}
}else{
nodeMap.put(child.getName(), child);
}
}

这个循环是您的代码中的问题。当您使用迭代器时,您无法修改底层集合。在这种情况下,您在此循环中迭代“children”,并且在调用“node.removeChildNode( child )”时从基础列表中删除项目。

解决方案是在迭代“子”列表之前克隆它。

List< TreeLayoutNode > children = node.getChildren().clone();

这意味着您不再迭代该方法后面正在编辑的列表。

您还可以创建另一个列表来存储完成迭代后要删除的子节点。

List< TreeLayoutNode > removedChildren = new LinkedList< >();
// Iterate over the elements, adding children to be removed to removedChildren
for( TreeLayoutNode child : removedChildren ) {
node.removeChildNode( child );
}

最后,您可以使用“it.remove()”从底层集合中删除该元素。这种方法的缺点是破坏了封装性。

// node.removeChildNode( child )
it.remove();

关于合并树结构中的节点时出现 java.util.ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25322328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com