1

I am trying to understand generics and the tree structure and stuck on the following issue...

I have created 3 classes 1) Node 2) Person 3) NodeTest

import java.util.*;

public class Node<T>
{
    private Node<T> root; // a T type variable to store the root of the list
    private Node<T> parent; // a T type variable to store the parent of the list
    private List<Node<T>> children = new ArrayList<Node<T>>(); // a T type list to store the children of the list

    // default constructor
    public Node(){ }

    // constructor overloading to set the parent
    public Node(Node<T> parent)
    {
        this.setParent(parent);
        //this.addChild(parent);
    }

    // constructor overloading to set the parent of the list  
    public Node(Node<T> parent, Node<T> child)
    {
        this(parent);
        this.children.add(child);
    }


    public void addChild(Node<T> child)
    {
        this.children.add(child); // add this child to the list
    }

    public void removeChild(Node<T> child)
    {
        this.children.remove(child); // remove this child from the list
    }

    public Node<T> getRoot() {
        return root;
    }

    public boolean isRoot()
    {
        return this.root != null; // check to see if the root is null if yes then return true else return false
    }

    public void setRoot(Node<T> root) {
        this.root = root;
    }

    public Node<T> getParent() {
        return parent;
    }

    public void setParent(Node<T> parent) {
        this.parent = parent;
    }

    public boolean hasChildren()
    {
        return this.children.size()>0;
    }

    public Node<T>[] children()
    {
        return (Node<T>[]) children.toArray(new Node[children.size()]);
    }

    public Node<T>[] getSiblings()
    {

        if(this.isRoot()==false)
        {
            System.out.println("this is not root");
        }

        List<Node<T>> tempSiblingList = new ArrayList<Node<T>>();

        //this.parent.children() isn't working for me
        //hence i tried to get around it next two lines
        Node<T> parent =  this.parent;

        Node<T>[] children =  parent.children();

        for(int i=0; i<children.length; i++)
        {
            if(this!=children[i])
            {
                tempSiblingList.add(children[i]);
            }
        }
        return (Node<T>[]) tempSiblingList.toArray(new Node[children.length]);
    }
}






public class Person {

    private String name;
    private int age;
    private String status;

    public Person(String name, int age, String status)
    {
        this.setName(name);
        this.setAge(age);
        this.setStatus(status);
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

My question is how i can go about initializing the Node class Person class...

i have tried

Person rootPerson = new Person("root", 80, "Alive");

Node<Person> root = new Node<Person>(rootPerson);

but it isn't working for me...

also need help with the getSibilings()

Mat
  • 202,337
  • 40
  • 393
  • 406
A Gilani
  • 417
  • 1
  • 7
  • 23

2 Answers2

1

You're passing in a Person to a constructor that needs a Node<Person>

If this is a tree you need both a variable for the parent as well as the object the tree contains.

public Node(Node<T> parent,T value)
dfb
  • 13,133
  • 2
  • 31
  • 52
  • I am trying to build a tree eventually... I am working on the Node class for now... It is a college assignment and the teacher never taught us generics... Now i fully understand your reply... but just cannot figure out how i can initialize this i have tried doing Node> root = new Node>(new Node(rootPerson)); but that didn't work either... – A Gilani Apr 23 '12 at 00:14
  • Node> root = new Node>(new Node(rootPerson)); – A Gilani Apr 23 '12 at 00:21
0

Your node class has no member for storing a value:

class Node<T>
{
    ...
    private T value;
    ...
}

You have no Node constructor taking an element type:

...
public node (T value)
{
    this.value = value;
}
...

And, by definition one's siblings are the children of one's parent that are not yourself:

public Node<T>[] getSiblings ( )
{
    if (parent == null)
        return null;

    List<Node<T>> siblings = new ArrayList<Node<T>>( );
    Collections.copy(siblings, parent.children);
    siblings.remove(this);

    return siblings.toArray(new Node<T>[]{});
}

Caveat: none of the above code tested.

Also, it appears that you're modelling a family tree? If so, please be aware that the strict hierarchical model you're following does not actually model reality very well, as famously chronicled here.

EDIT: in response to comments.

To initialise the class, you should first make the changes I mention above - make a member so that each Node can store a value, and make constructors that can take a value.

In this regard, @spinning_plate has it right: as well as the one taking a value that I've shown, you'll need one taking a value and a parent. A complete implementation of their constructor might look like the following:

public Node<T> (Node<T> parent, T value)
{
    this.parent = parent;
    this.value = value;

    // Don't forget: if you have a parent, you are their child.
    parent.addChild(this);
}

Then you can make a simple tree as follows:

Person rootPerson = new Person("root", 80, "alive");
Node<Person> rootNode = new Node<Person>(rootPerson); // This uses my constructor

Person son = new Person("son", 50, "alive");
Node<Person> sonNode = new Node<Person>(rootPerson, son); // This uses spinning_plate's constructor
Community
  • 1
  • 1
Mac
  • 14,615
  • 9
  • 62
  • 80
  • Thanks for your reply... I did understand the logistics of the getSiblings method... but the whole issue is at the parent.children(); the parent isn't exposing children array list or the method i created children() – A Gilani Apr 23 '12 at 00:22
  • Note that `private` only means private to *other* classes: instances of classes (objects) can access private members of other instances of the same class: in this case, one `Node` is quite ok to access the `children` list of another, even though it is marked private. It could, of course, use the `children()` method too - it's just easier using the list than an array. Also, note that I did address more than just the `getSiblings()` issue. – Mac Apr 23 '12 at 00:29
  • You post helped me a lot... and i have sorted my problems for now :-) however the return siblings.toArray(new Node[]{}) raise error of not being able to make an array of generic type so removing the part solves the issue for now... but in runtime it gives nullpointer exception... – A Gilani Apr 23 '12 at 00:35
  • That's what I meant by "it's not tested": I wasn't sure offhand about the anonymous array (the `new Node[]{}`). As for the null pointer exception, where does the compiler say it's occurring? – Mac Apr 23 '12 at 00:39
  • on the if(this.parent.children.size()>0) but i think i know the reason because when i initialize the class as Node root = new Node(rootPerson); in the constructor Public Node(T child){this.child = child} i need to set the parent of it as well... am i right... and the parent is the parent who is adding this as the child... else set this as null for now...? – A Gilani Apr 23 '12 at 00:42
  • That seems right - the root doesn't have a parent, hence `parent` will be null for the root node. This is why I have a check in my code above for `if (parent == null)`, to prevent exactly this kind of problem. – Mac Apr 23 '12 at 00:45
  • suppose i have a 'Node root = new Node(rootPerson);' and a 'Node son = new Node(sonPerson);' 'root.addChild(sonPerson);' – A Gilani Apr 23 '12 at 00:53