Recursive TreeView creation with the data provided in this question? - java

I have a Treeview TreeView<MyType> which I'd like to fill recursively from a MyType root object. The structure of the class MyType is the following:
public class MyType {
private Set<MyType> children = new HashSet<>();
public Set<MyType> getChildren() {
return children;
}
public void setChildren(Set<MyType> children) {
this.children = children;
}
}
So as you can see, the MyType root/parent has children of the same type, and those children can also have children from the same type. In practice, the depth between the root and its furthermost inheritant is no greater than 1000 level.
I want to fill the Treeview TreeView<MyType> recursively with tree items TreeItem<MyType>in the same tree structure as the data is stored in the MyType root file.
This is what I've tried so far but it's not working:
void buildTree(MyType parent, TreeItem<MyType> result) {
for (MyType child : parent.getChildren()) {
if (child.getChildren() == null || child.getChildren().isEmpty()) {
result.getChildren().add(new TreeItem<MyType>(child));
}
else {
TreeItem<MyType> tmp = new TreeItem<>(child);
buildTree(child, tmp);
}
}
}
Is it possible to make the filling work with the data structure provided?

It's more convenient to
A. Return TreeItems instead of passing both MyType and TreeItem to the recursive method calls.
B. Treat leafs as terminal cases instead of handling terminal cases at parents of leafs
This allows you to write the following code:
private TreeItem<MyType> buildSubtree(MyType root) {
TreeItem<MyType> result = new TreeItem<>(root);
if (root.getChildren() != null) {
for (MyType child : root.getChildren()) {
result.getChildren().add(buildSubtree(child));
}
}
return result;
}

Ok, I just figured it out. This is working as expected.
void buildTree(MyType parent, TreeItem<MyType> result) {
for (MyType child : parent.getChildren()) {
if (child.getChildren() == null || child.getChildren().isEmpty()) {
result.getChildren().add(new TreeItem<MyType>(child));
}
else {
TreeItem<MyType> tmp = new TreeItem<>(child);
buildTree(child, tmp);
result.getChildren().add(tmp);
}
}
}

Related

Deep copy a recursive list in Java with circular references

I have the class:
public class Node
{
private String id;
private List<Node> children;
}
I need to create a deep copy of a List of it List, but given that there might circular references I was trying implementing the Cloneable interface and overriding the clone method but I keep getting Stackoverflow exception, so I wonder if there is a way to deep copy it that's fast and removes the circular dependencies in the process?
Class using cloneable, when I try to clone and it has circular references I get the error mention about
public class Node implements Cloneable
{
private String id;
private List<Node> children;
#Override
public Object clone() throws CloneNotSupportedException {
Node clone = (Node) super.clone();
if (children != null) {
List<Node> cloneChildren = new ArrayList<>(children.size());
for (Node child : children) {
cloneChildren.add((Node) child.clone());
}
clone.setChildren(cloneChildren);
}
return clone;
}
public List<Node> getChildren() {
return children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
}
The easiest approach is to use an IdentityHashMap<Node,Node> to keep track of previously seen Nodes, mapping Nodes to be copied with Nodes copied thus far.
public Node copy() {
Map<Node,Node> copied = new IdentityHashMap<>();
return copy(copied, this);
}
private static Node copy(Map<Node,Node> copied, Node orig) {
Node existing = copied.get(orig);
if (existing != null) {
return existing;
}
Node copy = new Node();
copy.id = orig.id;
copy.children = new ArrayList<>();
copied.put(orig, copy);
for (Node child : orig.children) {
copy.children.add(copy(copied, child));
}
return copy;
}
(As usual, code compiled but not tested.)
I was thinking there is a 'clever' approach using Floyd's Tortoise and Hare Algorithm, but this is complicated by it not being a singly-linked list.

Vaadin 10+ Tree Grid: Hierarchies and how they work?

I have been trying to do a Vaadin tree grid with a more complex hierarchy. Since the documentation for this framework is very obscure and feels tad incomplete, I found this blog thread that helped me out only to get multiple children to a single parent.
However, I want to have a much more complex system where the children would have their own branches (children of children?).
For example:
So now I am stuck with this bit of code and I am unsure if I am going the right way or not.
TreeGrid<TreeDto> grid = new TreeGrid<>(TreeDto.class);
grid.setHierarchyColumn("name");
List<TreeDto> parenlist = new ArrayList<TreeDto>();
List<TreeDto> childList = new ArrayList<TreeDto>();
for(DataDepartment department : departmentLists)
{
TreeDto parent = new TreeDto(department.getDepName(), null);
for(DataGeneralSection section: sectionList)
{
childList.add(new TreeDto(section.getSection(), parent));
}
parenlist.add(parent);
}
List<TreeDto> newList = new ArrayList<TreeDto>(parenlist);
newList.addAll(childList);
newList.forEach(p -> grid.getTreeData().addItem(p.getParent(), p));
abteilungenTabs.add(grid);
Does anybody have any idea how I can achieve the hierarchy I want?
You can just continue deeper with your current approach. If you have a lot of items, you might want to consider a data provider like Simon Martinelli suggested.
public class MainView extends VerticalLayout {
public MainView() {
TreeGrid<TreeItem> treeGrid = new TreeGrid<>();
treeGrid.addHierarchyColumn(TreeItem::getValue);
setSizeFull();
treeGrid.setSizeFull();
for (Company company: getCompanies()) {
TreeItem companyItem = new TreeItem(company.getCompanyName());
treeGrid.getTreeData().addItem(null, companyItem);
for(Department department: company.getDepartments()) {
TreeItem departmentItem = new TreeItem(department.getName());
treeGrid.getTreeData().addItem(companyItem, departmentItem);
for(Employee employee: department.getEmployees()) {
TreeItem employeeItem = new TreeItem(employee.getFullName());
treeGrid.getTreeData().addItem(departmentItem, employeeItem);
}
}
}
add(treeGrid);
}
}
You must use a HierachicalDataProvider that provides the data.
For example:
dataProvider = new AbstractBackEndHierarchicalDataProvider<>() {
#Override
public int getChildCount(HierarchicalQuery<TreeNode, Void> hierarchicalQuery) {
if (hierarchicalQuery.getParent() == null) {
if (root == null) {
return 0;
} else {
return root.getChildren().size();
}
} else {
return hierarchicalQuery.getParent().getChildren().size();
}
}
#Override
public boolean hasChildren(TreeNode treeNode) {
return !treeNode.getChildren().isEmpty();
}
#Override
protected Stream<TreeNode> fetchChildrenFromBackEnd(HierarchicalQuery<TreeNode, Void> hierarchicalQuery) {
if (hierarchicalQuery.getParent() == null) {
if (root == null) {
return Stream.empty();
} else {
return root.getChildren().stream().skip(hierarchicalQuery.getOffset()).limit(hierarchicalQuery.getLimit());
}
} else {
return hierarchicalQuery.getParent().getChildren().stream().skip(hierarchicalQuery.getOffset()).limit(hierarchicalQuery.getLimit());
}
}
};
treeGrid.setDataProvider(dataProvider);

Randomly Generate a Tree Structure Consisting of Objects with their Parents

I'm trying to randomly generate a tree structure of objects that look something like the following:
Branch parent = new Branch("Start");
Branch branch1 = new Branch(parent, "Branch 1");
Branch branch2 = new Branch(parent, "Branch 2");
Branch branch21 = new Branch(branch2, "Branch 2.1");
Branch branch22 = new Branch(branch2, "Branch 2.2");
I know how to create objects manually, and how to generate random numbers, and I've seen some stuff on randomly generating nodes for creating fractals, but I'm pretty lost all the sudden, as I've never had to programmatically generate objects before.
Any ideas as to where to start, or what technique to use would be appreciated.
Typically, when building such items it's good to have a designed in and out. Otherwise, you will find yourself having to support many methods of application to support the intended result.
Hope this helps!
Try something along the following :)
Branch start = new Branch();
CreateChildren(start);
const int ChildrenLimitCheck = 0;
private void CreateChildren(Branch parent) {
//Use a limit variable so that you can decrease, and if it's equal to a sepcific number(usually 0) exit.
int Limit = (int) (Math.random() * 5);
//Call the function that's recursive, inside of a function that isn't recursive. This gives you a clean way to interface with the recursive function without excessive lines of code in other areas
generateChildren(parent,Limit);
}
private void generateChildren(Branch parent,int limit) {
//Check to see if we've hit our minimum. If so, exit out of the logic
if(limit == ChildrenLimitCheck)
return;
//Specify the random number of branches created in this instance
int numberOfBranches = (int) (Math.random() * 5);
for (int i = 0; i < numberOfBranches; i++) {
Branch child = new Branch(parent);
parent.Children.Add(child);
//Depending on what you want to do, either pass i or pass limit. If you don't use limit, you can remove it from this function :)
//If you pass i, try doing:
//for (int i = numberOfBranches; i > 0; i--)
//So that you can eventually get down to 0, to automatically stop your recursive calls with the above return statement.
//Seems you just want to run a loop for xxx number of times. This will still grant that, but you won't have to guess the upper limit
//of numberOfBranches to exit on, and you'll be able to exit cleanly
//This may be what caused your stackoverflow error. For all recursive functions, you need an exit condition or it will run indefinately
generateChildren(child,--limit);
//generateChildren(child,i);
}
}
I do this quite often and I can definately help in some areas of efficiency.
Try logic similar to the following. Place a breakpoint at Console.Write to see depth. This is a C++ object oriented approach, which I personally prefer over LINQ for performance. I didn't fine tune this, so LINQ may be faster. But if you know what you're doing, you can significantly increase performance via custom methods and inheritance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication11
{
public class Branch
{
//Branch Name
public string BranchName { get; set; }
//Add depth
public List<Branch> Children = new List<Branch>();
//Add a parent
public Branch Parent = null;
public Branch()
{
}
public Branch(string BranchName)
{
this.BranchName = BranchName;
}
public Branch(Branch Parent, string BranchName)
{
this.Parent = Parent;
this.BranchName = BranchName;
}
//Internal Functions
public bool HasParent()
{
return this.Parent != null;
}
public Branch getParent()
{
return this.Parent;
}
}
//Wrap a list inside of a class so we can have leverage over the add, and create our own functions for our need
public class BranchList
{
public List<Branch> branchParentList = new List<Branch>();
public void AddBranchToParent(Branch parent, Branch child)
{
foreach (Branch node in branchParentList)
{
if (node == parent)
{
node.Children.Add(child);
}
}
}
public void AddBranchAsChild(string parent, Branch child)
{
foreach (Branch node in branchParentList)
{
if (node.BranchName == parent)
{
node.Children.Add(child);
return;//Exit out, don't do the other loop. We found it
}
//Depth
AddBranchAsChildInChildren(node, child,parent);
}
}
public void AddBranchAsChildInChildren(Branch branch,Branch Child,string parent)
{
foreach(Branch child in branch.Children)
{
if (child.BranchName == parent)
child.Children.Add(Child);
}
}
public void AddBranchAsChildInChildren(Branch branch, string Child, string parent)
{
foreach (Branch child in branch.Children)
{
if (child.BranchName == parent)
child.Children.Add(new Branch() { BranchName=Child });
}
}
public void AddBranchAsChild(string parent, string child)
{
foreach (Branch node in branchParentList)
{
if (node.BranchName == parent)
{
node.Children.Add(new Branch() { BranchName = child });
return;
}
//Depth
AddBranchAsChildInChildren(node, child, parent);
}
}
public void AddBranchAsParent(Branch Branch, Branch Child)
{
if (branchParentList.Contains(Branch) == false)
throw new Exception("Parent exists");
foreach (Branch b in branchParentList)
{
if (b == Child)
{
b.Parent = Branch;
}
}
}
public void AddParent(Branch Parent)
{
if (branchParentList.Contains(Parent))
throw new Exception("Parent exists");
this.branchParentList.Add(Parent);
}
}
//Wrap the list, use it as an interface
public class BranchManager
{
public BranchList branchList = new BranchList();
public BranchManager()
{
}
public void AddParent(Branch Branch)
{
branchList.AddParent(Branch);
}
public void AddBranchAsChild(Branch Parent, Branch Child)
{
branchList.AddBranchToParent(Parent, Child);
}
public void AddBranchAsChild(string ParentName, Branch Child)
{
branchList.AddBranchAsChild(ParentName, Child);
}
public void AddBranchAsChild(string ParentName, string ChildName)
{
branchList.AddBranchAsChild(ParentName, ChildName);
}
}
class Program
{
static void Main(string[] args)
{
/*
Branch parent = new Branch("Start");
Branch branch1 = new Branch(parent, "Branch 1");
Branch branch2 = new Branch(parent, "Branch 2");
Branch branch21 = new Branch(branch2, "Branch 2.1");
Branch branch22 = new Branch(branch2, "Branch 2.2");
*/
BranchManager branchManager = new BranchManager();
branchManager.AddParent(new Branch("Start"));
branchManager.AddBranchAsChild("Start", "Branch 1");
branchManager.AddBranchAsChild("Start", "Branch 2");
branchManager.AddBranchAsChild("Branch 2", "Branch 2.1");
branchManager.AddBranchAsChild("Branch 2", "Branch 2.2");
Console.WriteLine(branchManager.branchList.branchParentList.Count);
}
}
}
Best guess so far, using a recursive function to handle the randomly generating children & parents:
Branch start = new Branch();
generateChildren(start);
private void generateChildren(Branch parent) {
int numberOfBranches = (int) (Math.random() * 5);
for (int i = 0; i < numberOfBranches; i++) {
Branch child = new Branch(parent);
generateChildren(child);
}
}
It properly creates a list of Branch objects with linked parents. I ran into a StackOverflow error until I wrapped it in a counter that limits the total number of branches.
The real question is: Is there a non-recursive way to handle it?

Looping through java recursive references

I was writing a simple linked list implementation and the corresponding Trigger class like this:
public class Trigger {
public static void main(String[] args) {
LinkedList lin = new LinkedList();
lin.add(3);
lin.add(4);
lin.add(5);
lin.display();
}
}
public class LinkedList {
Item startItem;
LinkedList() {
startItem = new Item();
}
public void add(Integer newValue) {
if(startItem.value == null) {
startItem.value = newValue;
return;
}
Item tempItem = new Item();
tempItem.value = newValue;
while(startItem.next != null) {
startItem = startItem.next;
}
startItem.next = tempItem;
}
public void display() {
while(true) {
System.out.println("\t"+ startItem.value);
if(startItem.next == null) {
break;
} else {
startItem = startItem.next;
}
}
}
class Item {
Integer value;
Item next;
Item() {
this.value = null;
this.next = null;
}
}
}
The problem is, only the last two additions are getting retained and the previous additions are discarded. This is (of course) because i keep changing the object that the reference startItem points to. My question is, given a recursive structure like this, what is the correct looping mechanism? I know that in a linked list, there is no need to get to the end of the list to perform addition. Linked list structure is used as a context to ask about looping through recursive structures. Thanks.
Your basic structure is correct. You just need to add one line before you start looping...
Item currentItem = startItem;
while(currentItem.next != null) {
currentItem = currentItem.next;
}
The only time the field startItem should be changed is in your first check if its value is null. It's reference should never be changed as it should always point to the start of the structure. Consider making it final to enforce this.

How do I get all nodes in a parent in JavaFX?

In C# I found a method that was pretty sweet that allowed you to get all the descendants and all of THEIR descendants from a specified control.
I'm looking for a similar method for JavaFX.
I saw that the Parent class is what I want to work with since it is the class from which all Node classes that bear children are derived.
This is what I have so far (and I haven't really found anything on google with searches like "JavaFX get all nodes from a scene"):
public static ArrayList<Node> GetAllNodes(Parent root){
ArrayList<Node> Descendents = new ArrayList<>();
root.getChildrenUnmodifiable().stream().forEach(N -> {
if (!Descendents.contains(N)) Descendents.add(N);
if (N.getClass() == Parent.class) Descendents.addAll(
GetAllNodes((Parent)N)
);
});
}
So how do I tell if N is a parent (or extended from a parent)? Am I doing that right? It doesn't seem to be working... It's grabbing all the nodes from the root (parent) node but not from the nodes with children in them. I feel like this is something that's probably got an answer to it but I'm just asking the question... wrong. How do I go about doing this?
public static ArrayList<Node> getAllNodes(Parent root) {
ArrayList<Node> nodes = new ArrayList<Node>();
addAllDescendents(root, nodes);
return nodes;
}
private static void addAllDescendents(Parent parent, ArrayList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
nodes.add(node);
if (node instanceof Parent)
addAllDescendents((Parent)node, nodes);
}
}
I use this,
public class NodeUtils {
public static <T extends Pane> List<Node> paneNodes(T parent) {
return paneNodes(parent, new ArrayList<Node>());
}
private static <T extends Pane> List<Node> paneNodes(T parent, List<Node> nodes) {
for (Node node : parent.getChildren()) {
if (node instanceof Pane) {
paneNodes((Pane) node, nodes);
} else {
nodes.add(node);
}
}
return nodes;
}
}
Usage,
List<Node> nodes = NodeUtils.paneNodes(aVBoxOrAnotherContainer);
This source code uses the references of the existing nodes. It does not clone them.
This seems to get ALL nodes.
(In Kotlin)
fun getAllNodes(root: Parent): ArrayList<Node> {
var nodes = ArrayList<Node>()
fun recurseNodes(node: Node) {
nodes.add(node)
if(node is Parent)
for(child in node.childrenUnmodifiable) {
recurseNodes(child)
}
}
recurseNodes(root)
return nodes
}
I'd like to add to Hans' answer, that you have to check if parent is a SplitPane. Because SplitPanes have an empty list using getUnmodifiableChildren(), you'll have to use getItems() instead. (I do not know if there are other parents that do not provide their children via getUnmodifiableChildren(). SplitPane was the first I found...)
Unfortunately this won't get subnodes for most container components. If you try a TabPane as parent, you'll find no children, but you can find tabs in it with getTabs(). The same is with SplitPane and other. So every container will require a specific approach.
You could use node.lookupAll("*"), but it also doesn't look inside.
The solution could be a "Prototype" pattern - creating a meta class with common interface of getChildren() method, which is realized in subclasses - one for each type.
Approach example is given here.
This works for me:
public class FXUtil {
public static final List<Node> getAllChildren(final Parent parent) {
final List<Node> result = new LinkedList<>();
if (parent != null) {
final List<Node> childrenLvl1 = parent.getChildrenUnmodifiable();
result.addAll(childrenLvl1);
final List<Node> childrenLvl2 =
childrenLvl1.stream()
.filter(c -> c instanceof Parent)
.map(c -> (Parent) c)
.map(FXUtil::getAllChildren)
.flatMap(List::stream)
.collect(Collectors.toList());
result.addAll(childrenLvl2);
}
return result;
}
}

Categories

Resources