I need to create a tree structure similar as the attached image in Java. I've found some questions related to this one but I haven't found a convincing and well explained response.
The application business consists in food super categories (main courses, desserts and other). Each of these categories can have parent items or children items and so on.
import java.util.ArrayList;
import java.util.List;
public class Node<T> {
private List<Node<T>> children = new ArrayList<Node<T>>();
private Node<T> parent = null;
private T data = null;
public Node(T data) {
this.data = data;
}
public Node(T data, Node<T> parent) {
this.data = data;
this.parent = parent;
}
public List<Node<T>> getChildren() {
return children;
}
public void setParent(Node<T> parent) {
parent.addChild(this);
this.parent = parent;
}
public void addChild(T data) {
Node<T> child = new Node<T>(data);
child.setParent(this);
this.children.add(child);
}
public void addChild(Node<T> child) {
child.setParent(this);
this.children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRoot() {
return (this.parent == null);
}
public boolean isLeaf() {
return this.children.size() == 0;
}
public void removeParent() {
this.parent = null;
}
}
Example:
import java.util.List;
Node<String> parentNode = new Node<String>("Parent");
Node<String> childNode1 = new Node<String>("Child 1", parentNode);
Node<String> childNode2 = new Node<String>("Child 2");
childNode2.setParent(parentNode);
Node<String> grandchildNode = new Node<String>("Grandchild of parentNode. Child of childNode1", childNode1);
List<Node<String>> childrenNodes = parentNode.getChildren();
Accepted answer throws a java.lang.StackOverflowError when calling the setParent or addChild methods.
Here's a slightly simpler implementation without those bugs:
public class MyTreeNode<T>{
private T data = null;
private List<MyTreeNode> children = new ArrayList<>();
private MyTreeNode parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode child) {
child.setParent(this);
this.children.add(child);
}
public void addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<>(data);
this.addChild(newChild);
}
public void addChildren(List<MyTreeNode> children) {
for(MyTreeNode t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode parent) {
this.parent = parent;
}
public MyTreeNode getParent() {
return parent;
}
}
Some examples:
MyTreeNode<String> root = new MyTreeNode<>("Root");
MyTreeNode<String> child1 = new MyTreeNode<>("Child1");
child1.addChild("Grandchild1");
child1.addChild("Grandchild2");
MyTreeNode<String> child2 = new MyTreeNode<>("Child2");
child2.addChild("Grandchild3");
root.addChild(child1);
root.addChild(child2);
root.addChild("Child3");
root.addChildren(Arrays.asList(
new MyTreeNode<>("Child4"),
new MyTreeNode<>("Child5"),
new MyTreeNode<>("Child6")
));
for(MyTreeNode node : root.getChildren()) {
System.out.println(node.getData());
}
Here is my implementation in java for your requirement.
In the treeNode class i used generic array to store the tree data. we can also use arraylist or dynamic array to store the tree value.
public class TreeNode<T> {
private T value = null;
private TreeNode[] childrens = new TreeNode[100];
private int childCount = 0;
TreeNode(T value) {
this.value = value;
}
public TreeNode addChild(T value) {
TreeNode newChild = new TreeNode(value, this);
childrens[childCount++] = newChild;
return newChild;
}
static void traverse(TreeNode obj) {
if (obj != null) {
for (int i = 0; i < obj.childCount; i++) {
System.out.println(obj.childrens[i].value);
traverse(obj.childrens[i]);
}
}
return;
}
void printTree(TreeNode obj) {
System.out.println(obj.value);
traverse(obj);
}
}
And the client class for the above implementation.
public class Client {
public static void main(String[] args) {
TreeNode menu = new TreeNode("Menu");
TreeNode item = menu.addChild("Starter");
item = item.addChild("Veg");
item.addChild("Paneer Tikka");
item.addChild("Malai Paneer Tikka");
item = item.addChild("Non-veg");
item.addChild("Chicken Tikka");
item.addChild("Malai Chicken Tikka");
item = menu.addChild("Main Course");
item = item.addChild("Veg");
item.addChild("Mili Juli Sabzi");
item.addChild("Aloo Shimla Mirch");
item = item.addChild("Non-veg");
item.addChild("Chicken Do Pyaaza");
item.addChild("Chicken Chettinad");
item = menu.addChild("Desserts");
item = item.addChild("Cakes");
item.addChild("Black Forest");
item.addChild("Black Current");
item = item.addChild("Ice Creams");
item.addChild("chocolate");
item.addChild("Vanilla");
menu.printTree(menu);
}
}
OUTPUT
Menu
Starter
Veg
Paneer Tikka
Malai Paneer Tikka
Non-veg
Chicken Tikka
Malai Chicken Tikka
Main Course
Veg
Mili Juli Sabzi
Aloo Shimla Mirch
Non-veg
Chicken Do Pyaaza
Chicken Chettinad
Desserts
Cakes
Black Forest
Black Current
Ice Creams
chocolate
Vanilla
Since #Jonathan's answer still consisted of some bugs, I made an improved version. I overwrote the toString() method for debugging purposes, be sure to change it accordingly to your data.
import java.util.ArrayList;
import java.util.List;
/**
* Provides an easy way to create a parent-->child tree while preserving their depth/history.
* Original Author: Jonathan, https://stackoverflow.com/a/22419453/14720622
*/
public class TreeNode<T> {
private final List<TreeNode<T>> children;
private TreeNode<T> parent;
private T data;
private int depth;
public TreeNode(T data) {
// a fresh node, without a parent reference
this.children = new ArrayList<>();
this.parent = null;
this.data = data;
this.depth = 0; // 0 is the base level (only the root should be on there)
}
public TreeNode(T data, TreeNode<T> parent) {
// new node with a given parent
this.children = new ArrayList<>();
this.data = data;
this.parent = parent;
this.depth = (parent.getDepth() + 1);
parent.addChild(this);
}
public int getDepth() {
return this.depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
public List<TreeNode<T>> getChildren() {
return children;
}
public void setParent(TreeNode<T> parent) {
this.setDepth(parent.getDepth() + 1);
parent.addChild(this);
this.parent = parent;
}
public TreeNode<T> getParent() {
return this.parent;
}
public void addChild(T data) {
TreeNode<T> child = new TreeNode<>(data);
this.children.add(child);
}
public void addChild(TreeNode<T> child) {
this.children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRootNode() {
return (this.parent == null);
}
public boolean isLeafNode() {
return (this.children.size() == 0);
}
public void removeParent() {
this.parent = null;
}
#Override
public String toString() {
String out = "";
out += "Node: " + this.getData().toString() + " | Depth: " + this.depth + " | Parent: " + (this.getParent() == null ? "None" : this.parent.getData().toString()) + " | Children: " + (this.getChildren().size() == 0 ? "None" : "");
for(TreeNode<T> child : this.getChildren()) {
out += "\n\t" + child.getData().toString() + " | Parent: " + (child.getParent() == null ? "None" : child.getParent().getData());
}
return out;
}
}
And for the visualization:
import model.TreeNode;
/**
* Entrypoint
*/
public class Main {
public static void main(String[] args) {
TreeNode<String> rootNode = new TreeNode<>("Root");
TreeNode<String> firstNode = new TreeNode<>("Child 1 (under Root)", rootNode);
TreeNode<String> secondNode = new TreeNode<>("Child 2 (under Root)", rootNode);
TreeNode<String> thirdNode = new TreeNode<>("Child 3 (under Child 2)", secondNode);
TreeNode<String> fourthNode = new TreeNode<>("Child 4 (under Child 3)", thirdNode);
TreeNode<String> fifthNode = new TreeNode<>("Child 5 (under Root, but with a later call)");
fifthNode.setParent(rootNode);
System.out.println(rootNode.toString());
System.out.println(firstNode.toString());
System.out.println(secondNode.toString());
System.out.println(thirdNode.toString());
System.out.println(fourthNode.toString());
System.out.println(fifthNode.toString());
System.out.println("Is rootNode a root node? - " + rootNode.isRootNode());
System.out.println("Is firstNode a root node? - " + firstNode.isRootNode());
System.out.println("Is thirdNode a leaf node? - " + thirdNode.isLeafNode());
System.out.println("Is fifthNode a leaf node? - " + fifthNode.isLeafNode());
}
}
Example output:
Node: Root | Depth: 0 | Parent: None | Children:
Child 1 (under Root) | Parent: Root
Child 2 (under Root) | Parent: Root
Child 5 (under Root, but with a later call) | Parent: Root
Node: Child 1 (under Root) | Depth: 1 | Parent: Root | Children: None
Node: Child 2 (under Root) | Depth: 1 | Parent: Root | Children:
Child 3 (under Child 2) | Parent: Child 2 (under Root)
Node: Child 3 (under Child 2) | Depth: 2 | Parent: Child 2 (under Root) | Children:
Child 4 (under Child 3) | Parent: Child 3 (under Child 2)
Node: Child 4 (under Child 3) | Depth: 3 | Parent: Child 3 (under Child 2) | Children: None
Node: Child 5 (under Root, but with a later call) | Depth: 1 | Parent: Root | Children: None
Is rootNode a root node? - true
Is firstNode a root node? - false
Is thirdNode a leaf node? - false
Is fifthNode a leaf node? - true
Some additional informations: Do not use addChildren() and setParent() together. You'll end up having two references as setParent() already updates the children=>parent relationship.
This tree is not a binary tree, so you need an array of the children elements, like List.
public Node(Object data, List<Node> children) {
this.data = data;
this.children = children;
}
Then create the instances.
In the accepted answer
public Node(T data, Node<T> parent) {
this.data = data;
this.parent = parent;
}
should be
public Node(T data, Node<T> parent) {
this.data = data;
this.setParent(parent);
}
otherwise the parent does not have the child in its children list
In answer
,it creates circular dependency.This can be avoided by removing parent inside Child nodes.
i.e,
public class MyTreeNode<T>{
private T data = null;
private List<MyTreeNode> children = new ArrayList<>();
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode child) {
this.children.add(child);
}
public void addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<>(data);
children.add(newChild);
}
public void addChildren(List<MyTreeNode> children) {
this.children.addAll(children);
}
public List<MyTreeNode> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Using the same example specified above,the output will be like this:
{ "data": "Root", "children": [
{
"data": "Child1",
"children": [
{
"data": "Grandchild1",
"children": []
},
{
"data": "Grandchild2",
"children": []
}
]
},
{
"data": "Child2",
"children": [
{
"data": "Grandchild3",
"children": []
}
]
},
{
"data": "Child3",
"children": []
},
{
"data": "Child4",
"children": []
},
{
"data": "Child5",
"children": []
},
{
"data": "Child6",
"children": []
} ] }
The process of assembling tree nodes is similar to the process of assembling lists. We have a constructor for tree nodes that initializes the instance variables.
public Tree (Object cargo, Tree left, Tree right) {
this.cargo = cargo;
this.left = left;
this.right = right;
}
We allocate the child nodes first:
Tree left = new Tree (new Integer(2), null, null);
Tree right = new Tree (new Integer(3), null, null);
We can create the parent node and link it to the children at the same time:
Tree tree = new Tree (new Integer(1), left, right);
Related
Having requirement to read Parent and children representation in tree structure.
Root Parent Child Depth
AAA - - 0
AAA AAA BBB 1
AAA AAA CCC 1
AAA BBB BBB1 2
AAA CCC CCC1 2
As you can see it AAA is root element and has two child BBB and CCC.
again BBB and CCC has children so on.
Would like to have as one node mapped with all its children.
Options
Created Treenode Class as mentioned below.
public class TreeNode<T> {
private final List<TreeNode<T>> children;
private TreeNode<T> parent;
private T data;
private int depth;
public TreeNode(T data) {
// a fresh node, without a parent reference
this.children = new ArrayList<>();
this.parent = null;
this.data = data;
this.depth = 0; // 0 is the base level (only the root should be on there)
}
public TreeNode(T data, TreeNode<T> parent) {
// new node with a given parent
this.children = new ArrayList<>();
this.data = data;
this.parent = parent;
this.depth = (parent.getDepth() + 1);
parent.addChild(this);
}
public int getDepth() {
return this.depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
public List<TreeNode<T>> getChildren() {
return children;
}
public void setParent(TreeNode<T> parent) {
this.setDepth(parent.getDepth() + 1);
parent.addChild(this);
this.parent = parent;
}
public TreeNode<T> getParent() {
return this.parent;
}
public void addChild(T data) {
TreeNode<T> child = new TreeNode<>(data);
this.children.add(child);
}
public void addChild(TreeNode<T> child) {
this.children.add(child);
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRootNode() {
return (this.parent == null);
}
public boolean isLeafNode() {
return (this.children.size() == 0);
}
public void removeParent() {
this.parent = null;
}
#Override
public String toString() {
String out = "";
out += "Node: " + this.getData().toString() + " | Depth: " + this.depth + " | Parent: " + (this.getParent() == null ? "None" : this.parent.getData().toString()) + " | Children: " + (this.getChildren().size() == 0 ? "None" : "");
for(TreeNode<T> child : this.getChildren()) {
out += "\n\t" + child.getData().toString() + " | Parent: " + (child.getParent() == null ? "None" : child.getParent().getData());
}
return out;
}
}
Received data as mentioned in above structure from DB as list
TreeNode<CompanyReport > root = null;
TreeNode<CompanyReport > firstChild = null;
for (CompanyReport report : reportList) {
if (report.getDepth() == 0) {
root = new TreeNode(report);
}
if (report .getDepth() == 1) {
firstChild = new TreeNode<CompanyReport >(report, root);
}
}
Here when Depth is 2 then want to map next child to its first child not to root element.
Could you please suggest how it should be done.
We can have deeper depth as well not restricted to 2 or 3 and it can not be binary tree structure as well. Its kind of n-array structure.
I am using the following code to convert a flat structure like:
test/test2/test3
test/test5/test2
test/test7/test5/test4
test/test7/test5/test9
into a tree like:
test
| | |
test2 test5 test7
| | |
test3 test2 test5
| |
test4 test9
The code:
import java.util.*;
class Tree
{
class Node
{
String data;
ArrayList<Node> children;
public Node(String data)
{
this.data = data;
children = new ArrayList<Node>();
}
public ArrayList<Node> getChildren()
{
return children;
}
public Node getChild(String data)
{
for(Node n : children)
if(n.data.equals(data))
return n;
return null;
}
}
private Node root;
public Tree()
{
root = new Node("");
}
public boolean isEmpty()
{
return root==null;
}
public void add(String str)
{
Node current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while(s.hasMoreElements())
{
str = (String)s.nextElement();
Node child = current.getChild(str);
if(child==null)
{
current.children.add(new Node(str));
child = current.getChild(str);
}
current = child;
}
}
public void get()
{
return root;
}
}
I use the "add" function to split the above flat paths to a tree and it works nicely and I am able to navigate forward. Though, I want to be able to navigate to the Node with a given path and also when I navigate to some Node, I want to be able to trace it to the root element. For example, if I navigate from test -> test2 -> test3, I want to get the path from the root like test/test2/test3.
I am new to Trees and the topic is confusing me a bit, your help is highly appreciated.
Edit: Added a visual representation.
public class Tree {
private final Node root = new Node(null, null);
public boolean isEmpty() {
return root.children.isEmpty();
}
public void add(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
parent.children.add(node = new Node(data, parent));
parent = node;
}
}
public Node get(String path) {
Node parent = root;
for (String data : path.split("/")) {
Node node = parent.getChild(data);
if (node == null)
return null;
parent = node;
}
return parent;
}
public static final class Node {
private final String data;
private final Node parent;
private final List<Node> children = new LinkedList<>();
public Node(String data, Node parent) {
this.data = data;
this.parent = parent;
}
public List<Node> getChildren() {
return Collections.unmodifiableList(children);
}
public Node getChild(String data) {
for (Node node : children)
if (node.data.equals(data))
return node;
return null;
}
public String getPath() {
Deque<String> nodes = new LinkedList<>();
Node node = this;
while (node.parent != null) {
nodes.addFirst(node.data);
node = node.parent;
}
return String.join("/", nodes);
}
#Override
public String toString() {
return data;
}
}
public static void main(String... args) {
Tree tree = new Tree();
tree.add("test/test2/test3");
tree.add("test/test5/test2");
tree.add("test/test7/test5/test4");
tree.add("test/test7/test5/test9");
Node node = tree.get("test/test7/test5/test9");
String path = node.getPath();
}
}
A simple way is to keep track of the parent node, then just follow the parents up the tree from the child:
Node currentNode = ...
ArrayList<Node> path = new ArrayList<>();
while(currentNode != null){
path.add(currentNode);
currentNode = currentNode.getParent();
}
Collections.reverse(path);
So your Node class would need a new constructor:
class Node {
String data;
ArrayList<Node> children;
Node parent;
Node(Node parent, String data){
// ...
}
// ...
// Null if this is the root, else returns the parent node
public Node getParent(){ return parent; }
}
I have constructed a Tree class as shown below:
public class Node {
private int label;
private ArrayList<Node> children;
private Node parent;
public Node(int label) {
this.label = label;
this.children = new ArrayList<Node>();
this.parent = null;
}
public void addChild(Node child) {
this.children.add(child);
}
public int getLabel() {
return this.label;
}
public ArrayList<Node> getChildren() {
return this.children;
}
public Node getParent() {
return this.parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
}
Assuming that I have a non binary Tree:
1
|
9
/ | \
3 0 7
How can I write a method in order to get the level of a leaf (say node labelled with 7) in a non-binary Tree?
public int getLevel() {
if (parent == null) return 0;
// Additional code is needed here
}
The level is often called the depth or height.
public int getLevel(){
Node temp = parent;
int depth = 0;
while(temp != null){
depth++;
temp = temp.parent;
}
return depth;
}
This will not work if there is a cycle of course, but there shouldn't be one in a tree anyways.
I have a Tree implementation but i want change ArrayList to simply array, i don't want use collection in java i just want use array but i don't know how i can replace ArrayList to simply array.
There is a code:
public class TreeNode {
private String data = null;
private List<TreeNode> children = new ArrayList<>();
int topSize;// I added it, since i know how is the size of Tree
private TreeNode[] children2 = new TreeNode[topSize];//I added it
private TreeNode parent = null;
public TreeNode(String data) {
this.data = data;
}
int i = 0;//I added it
public void addChild(TreeNode child) {
child.setParent(this);
this.children.add(child);
this.children2[i++] = child;//I added it
}
public void addChild(String data) {
TreeNode newChild = new TreeNode(data);
newChild.setParent(this);
children.add(newChild);
children2[i] = newChild;// I added it
}
public void addChildren(List<TreeNode> children) {
for (TreeNode t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<TreeNode> getChildren() {
return children;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
private void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getParent() {
return parent;
}
public static void main(String[] args) {
TreeNode root = new TreeNode("Root");
TreeNode child1 = new TreeNode("Child1");
child1.addChild("Grandchild1");
child1.addChild("Grandchild2");
TreeNode child2 = new TreeNode("Child2");
child2.addChild("Grandchild3");
root.addChild(child1);
root.addChild(child2);
root.addChild("Child3");
root.addChildren(Arrays.asList(
new TreeNode("Child4"),
new TreeNode("Child5"),
new TreeNode("Child6")
));
TreeNode mainRoot = new TreeNode("MainRoot");
mainRoot.addChildren(Arrays.asList(root));
for (TreeNode node : root.getChildren()) {
System.out.println(node.getData());
}
}
}
I create TreeNode[] children2 array and add int topSize, since i know what size tree will be.But it doesn't work correctly. I want Tree without collections from java.java.lang.ArrayIndexOutOfBoundsException: 0 in children2[i] = newChild;
The topSize variable is never assigned in our code, so it has the default value: 0. This means that children2 is an empty array. That's why you get an ArrayIndexOutOfBoundsException while putting something into it.
Try to initialize topSize with some value, for example:
int topSize = 10;
After this modification, your program runs with no exceptions.
I want to merge the node which has the same name, and add their children together.
But I got a java.util.ConcurrentModificationException exception:
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)
Following is the source.Could someone give any hints? Any suggestions will be welcomed.
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);
}
}
This loop is the problem in your code. When you are using an Iterator, you can not modify the underlying Collection. In this case you are iterating over 'children' in this loop, and you are removing items from the underlying list when you call 'node.removeChildNode( child )'.
A solution is to clone the 'children' list before you iterator over it.
List< TreeLayoutNode > children = node.getChildren().clone();
This means you are no longer iterating over the list that is being edited in the later on in the method.
You could also create another List to store children nodes to be removed after you are done iterating over it.
List< TreeLayoutNode > removedChildren = new LinkedList< >();
// Iterate over the elements, adding children to be removed to removedChildren
for( TreeLayoutNode child : removedChildren ) {
node.removeChildNode( child );
}
Finally you could use 'it.remove()' to remove the element from the underlying Collection. This method has the disadvantage of breaking encapsulation.
// node.removeChildNode( child )
it.remove();