在树结构中合并节点时发生java.util.ConcurrentModificationException
我想合并具有相同名称的节点,并将它们的子节点添加到一起。 但我得到了一个java.util.ConcurrentModificationException异常:在树结构中合并节点时发生java.util.ConcurrentModificationException,java,exception,tree,Java,Exception,Tree,我想合并具有相同名称的节点,并将它们的子节点添加到一起。 但我得到了一个java.util.ConcurrentModificationException异常: Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.
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;
}
}
}
公共类测试{
公共静态void main(字符串[]args)引发异常{
TreeLayoutNode根=新的TreeLayoutNode();
root.setName(“生产”);
TreeLayoutNode1=新的TreeLayoutNode();
node1.setName(“node1”);
TreeLayoutNode2=新的TreeLayoutNode();
node2.setName(“node1”);
TreeLayoutNode child1=新的TreeLayoutNode();
child1.设置名称(“child1”);
TreeLayoutNode child2=新的TreeLayoutNode();
child2.集合名(“child2”);
TreeLayoutNode child3=新的TreeLayoutNode();
child3.集合名(“child3”);
root.addChildNode(node1);
root.addChildNode(node2);
node1.addChildNode(child1);
node1.addChildNode(child2);
node2.addChildNode(child1);
node2.addChildNode(child3);
HashMap nodeMap=Maps.newHashMap();
合并节点(根,节点映射);
}
/**
*
*@param节点
*/
私有静态void合并节点(TreeLayoutNode节点、HashMap节点映射){
List children=node.getChildren();
if(CollectionUtils.isEmpty(儿童)){
返回;
}
Iterator it=children.Iterator();
while(it.hasNext()){
TreeLayoutNode子节点=it.next();
if(nodeMap.containsKey(child.getName())){
TreeLayoutNode duplicate=nodeMap.get(child.getName());
List childrenOfChild=child.getChildren();
if(CollectionUtils.isNotEmpty(childrenOfChild)){
对于(TreeLayoutNode single:childrenOfChild){
重复.addChildNode(单个);
}
node.removeChildNode(子节点);
合并节点(重复,节点映射);
}
}否则{
nodeMap.put(child.getName(),child);
}
}
}
}
公共类TreeLayoutNode{
私有字符串名称;
私有字符串父级;
私人长容量;
私人名单比例;
私人名单儿童;
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共字符串getParent(){
返回父母;
}
公共void setParent(字符串父级){
this.parent=parent;
}
公共长期服务能力(){
返回能力;
}
公共容量(长容量){
这个。容量=容量;
}
公共列表{
回报比例;
}
公共空间比例(列表比例){
这个比例=比例;
}
公共列表getChildren(){
返回儿童;
}
公共子项(列出子项){
这个。孩子=孩子;
}
public void addChildNode(TreeLayoutNode子节点){
if(children==null){
children=Lists.newArrayList();
}
setParent(this.getName());
添加(child);
}
public void removeChildNode(TreeLayoutNode子节点){
儿童。移除(儿童);
}
公共空间比例(比例){
如果(比例==null){
比例=列表。newArrayList();
}
比例。添加(比例);
}
公共int hashCode(){
返回name==null?0:name.hashCode();
}
公共布尔等于(对象o){
if(TreeLayoutNode的o实例){
TreeLayoutNode目标=(TreeLayoutNode)o;
if(this.name==null){
返回target.getName()==null;
}否则{
返回此.name.equals(target.getName());
}
}否则{
返回false;
}
}
}
异常堆栈跟踪是……当您尝试在迭代时修改集合时,会得到java.util.ConcurrentModificationExceptionit@alfasin我是否应该创建另一个树结构并向其中添加原始树节点以避免出现这种情况?@JBNizet我已对其进行了编辑。
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);
}
}
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 );
}
// node.removeChildNode( child )
it.remove();