Implementing a generic node [duplicate] - java

This question already has answers here:
What does the 'new' keyword actually do in Java, and should I avoid creating new objects?
(6 answers)
Closed 5 years ago.
I keep receiving an error when I'm trying to implement a node with generic data types. the node must be able to take an int input as well as a fraction input. what am i doing wrong? The compiler says that "method Node(A) is undefined for class BinarySearchtree
//creates a generic binary search tree class
public class BinarySearchTree<A> {
//the root of the node, which is the middle value
Node root;
//this constructor will add a node
public void addNode(A userNumber){
Node<A> newNode = Node<A>(A userNumber);
}//end addNode
public class Node<T>{
//this generic variable will become the user input either int or fraction
private T number;
//nodes that will become the left of right child of a parent node
Node<T> leftChild;
Node<T> rightChild;
//a node constructor that will take a generic input
Node(T number){
this.number = number;
}//end node constructor
}//end the Node class
}//end binary search tree

Instead of
Node<A> newNode = Node<A>(A userNumber);
use
Node<A> newNode = new Node<A>(A userNumber);
You don't have any method Node which the compiler gladly tells you about.

Related

Can a variable be declared in java using class name only?

Can a variable be declared in java using the name of a subclass? I found this piece of code about linked lists very confusing. See, how the head of the list has been declared. Can someone please explain?
class LinkedList
{
Node head; // head of list
/* Linked list Node*/
class Node
{
int data;
Node next;
// Constructor to create a new node
// Next is by default initialized
// as null
Node(int d)
{
data = d;
}
}
}
Yes, an object can indeed contain a reference to another object of the same type as an instance member.
For example, this is the standard class definition of a Linked List Node:
class Node {
int value;
Node next;
... // instance methods follow
}
You have the current node which must point to a reference of the next node in the linked list.

Proper way of using generics for composition of elements in java

Tree contains elements of TreeNode with data elements of type T.
I define as below
class TreeNode<T>
{
T data;
}
The following dosen't make sense.
class Tree<TreeNode<T>>
{
TreeNode<T> node;
}
then case 1
class Tree
{
TreeNode<T> node;
}
but above gives error at T in line 3.
then case 2
class Tree<N extends TreeNode<T>>
{
TreeNode<T> node;
}
compiler complains at T in line line 1 - T cannot be resolved.
but below case 3 compiler is happy
class Tree<T extends TreeNode<T>>
{
TreeNode<T> node;
}
but the above dosen't make sense. it will be true as in the case like T extends Comparable, but here it says that Tree contains elements of type subtype TreeNode containing data of type T, which inturn is of type T, which says that TreeNode also contain elements of type TreeNode which is not my intention.
What is the right way of defining that Tree contains elements of type TreeNode of data elements T ?
and Tree contains elements of subtype TreeNode ?
Is there any way to tell to the compiler that T is declared in TreeNode class ?
Also how to paramerize TreeNode and Tree saying that TreeNode contains elements of type T and also had pointers for TreeNode left child and right child ?

Return type error of linked list toUppercase method

I have a class called LString (a linked list class) that works with my other Node class. I have written a toUppercase() method that traverses the character sequence and converts lowercase to uppercase.
My issue is the return type, a problem I seem to have when coding a lot. I am unsure of how to return the required LString type, since even if I type return LString it recognizes it as a variable and gives the same incompatible types errors.
Here is the explicit error:
LString.java:134: error: incompatible types
return current;
^
required: LString
found: Node
How do I return this required type of LString in my method?
I am pretty new to Java, and getting a grasp on return types has seemed troublesome for me when writing this. Let me know if I should post my whole class. If my question is a little unclear let me know as well, I would like to be concise with the users in this forum.
As requested here is more of my code that specifies the declarations I have made in both classes.
My Node class:
public class Node{
public char data;
public Node next;
//constructors from page 956
public Node()
{
this('\0',null); //'\0' is null char for java
}
public Node(char initialData, Node initialNext)
{
data = initialData;
next = initialNext;
}
}
And my LString class (only constructor and my toUppercase method I will list):
public class LString{
private Node front = null; //first val in list
private Node back; //last val in list
private int size = 0;
private int i;
public LString(){
//construct empty list
Node LString = new Node();
front = null;
}
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return front;
}
}
If I need to provide anymore info let me know.
To return the required LString simply do:
return this;
Because LString is the class that contains the linked list's first node, and all the methods that modify the list should simply return it. Also notice that this line is doing nothing in the constructor, you can delete it:
Node LString = new Node();
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return front;
}
front is of type Node, but the signature of the method is public LString toUppercase(), which means that it is expected to return an LString instance.
Think about what it is that you actually want to return. You want to return an LString that contains uppercase characters, right? But that is already the instance that you are working with! So you can either return this:
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return this;
}
But in this case you will still need another method that prints out the uppercase characters:
LString lString = new LString();
...
...
lString.toUppercase(); //lString is already modified and contains uppercase characters! You
//don't have to "return" anything. If you returned "this" this
//line would be lString = lString.toUppercase(), but that's
//not buying you anything special.
System.out.println(lString.toString()); //Assuming you have a toString method
//that prints out the characters.
By calling the toUppercase instance method you have already modified your LString instance so there is really no need to return anything.

creating instance using self as argument

creating a doubly linked list with one node that points to itself
public DList(){
Dnode sentinel= new DNode(sentinel, null, sentinel);
}
for reference, Dnode constructor takes DNode(Dnode p, Object 0, Dnode n)
Is this valid code?
No, this is not valid.
You can't cant use sentinel variable in the expression that defines it.
You can however have a constructor, which makes the previous and next elements be itself (this):
class DList {
DList previous, next;
public DList() {
previous = this;
next = this;
}
}

static final variables in a generic class causing unchecked & rawtype warnings

Is it a design flaw to have a static final variable in a generic class? Consider the class below, all references to Node.SOIL give rise to warnings. What is a good way of going about solving this problem?
public class Node<E> {
private static int nodeCounter = 0;
#SuppressWarnings({ "unchecked", "rawtypes" })
public static final Node SOIL = new Node(null, null); // <-- HERE
public static void resetSOIL(){
SOIL.children = null; // <-- HERE
}
private Node<E> parent;
private Set<Node<E>> children;
protected Set<Node<E>> isomorphs;
private E data;
private int id;
public Node(Node<E> parent, E data){
this.parent = parent;
this.data = data;
this.id = ++nodeCounter;
}
public boolean isRoot(){
return (this.getParent() == SOIL);
}
// utility methods
....
}
You've defined a type Node<E> which represents a node in a tree of E's. For example, Node<Integer> is a node in a tree of Integers, and Node<String> is a node in a tree of Strings.
Now you want a variable SOIL that contains all the roots of these various trees of different types (hehe, soil, I get it now). Set aside the static field issue for now. What should the class of SOIL be? In other words, how do we declare and create the SOIL instance?
Node</*something1*/> SOIL = new Node</*something2*/>(null, null);
Since SOIL is going to have children that are Node<Integer> and Node<String> then it has to be something like Node<?> or Node<Object>. You can't instantiate an object using a wildcard type argument, so the best you can do is something like this:
Node<?> SOIL = new Node<Object>(null, null);
(If you use the Java 7 diamond construct new Node<>(...) it ends up using Object in this case anyway.)
The problem is, this still doesn't work. The way the Node<E> type is defined is as a homogeneous tree of E's. But one subtree of SOIL is a tree of Integers and another subtree is a tree of Strings, so SOIL wants to be a heterogeneous tree. Therefore, SOIL cannot be a Node<E> for any E.
At least, not in a type-safe fashion. You could write the code to do this, but you'd have to add some casts, and you'd get unchecked warnings. These warnings would tell you that this approach isn't working. For example, consider some code that takes a Node<E> and operates on all of its siblings (that is, the other children of its parent). Some code that took a Node<Integer> could call this and end up with a bunch of instances of Node<String> and start throwing ClassCastExceptions.
You might consider making SOIL a Set<Node<?>> and not making it be the parent of all the roots. You could make it a static field somewhere, but make it private.
It's not a design flaw to have a static final variable. The warning appears because you are declaring an instance of a generic type without providing a type parameter:
public static final Node SOIL = new Node(null, null); // <-- HERE
when the compiler is expecting something like:
public static final Node<SomeType> SOIL = new Node<SomeType>(null, null);
You could use this to avoid suppressWarnings and it works well:
private static final Node<Object> SOIL = new Node<Object>(null, null);
To answer to your other question:
Is it a design flaw to have a static final variable in a generic class?
No itsnt, it is even a good common practice to use it as default for null variables of type Node, aka the NULL object in Effective Java Programming

Categories