OOP Initializing instance variables with instances of child class - java

I am trying to implement the NullObject design pattern on my class Node:
class Node{
Node nextNode;
char key;
Node prevNode;
/*
Would like to initialize nextNode and prevNode to instance of
NullNode, something like this (I know what I am doing is wrong)
*/
Node() {
nextNode = new NullNode();
prevNode = new NullNode();
}
}
class NullNode extends Node {
....
}
With this code I get a StackOverflowError Exception. How can I tackle this issue?

You are getting a StackOverflow because the parent constructor is always called (see also: https://stackoverflow.com/a/527069/664108). In your case this results in endless recursion.
To avoid that, you will have to add a check in the Node constructor and call it explicitly from the NullNode constructor:
public class Node
{
Node nextNode;
char key;
Node prevNode;
Node() {
Node(true);
}
Node(boolean createNullNodes) {
if (createNullNodes) {
nextNode = new NullNode();
prevNode = new NullNode();
}
}
}
public class NullNode extends Node
{
NullNode() {
super(false);
}
}
A better solution for the NullObject pattern is using interfaces. This eliminates the constructor problem and also allows to remove the not needed nextNode and prevNode variables from the NullNode.
Example with interface:
public interface INode
{
public char getKey();
public INode getNext();
public INode getPrev();
// ...
}
public class Node implements INode
{
Node nextNode;
char key;
Node prevNode;
Node() {
nextNode = new NullNode();
prevNode = new NullNode();
}
public char getKey() {
return key;
}
public INode getNext() {
return nextNode;
}
public INode getPrev() {
return prevNode;
}
}
public class NullNode implements INode
{
public char getKey() {
return null;
}
public INode getNext() {
return this;
}
public INode getPrev() {
return this;
}
}

Normally we do not reference the Subclass in the Suerclass, this somehow breaks the inheritance relation.
In your code there is something even worse that will cause a StackoverflowException because the superclass creates an object with the default constructor of the subclass which in turns calls the default constructor of the superclass and it will go infinitely until your program crashes.
You can see an implementation of the Null Object Pattern here

Try this
public clas Node
{
Node nextNode;
char key;
Node prevNode;
Node() {
this(true);
}
Node(boolean createNullNodes) {
if (createNullNodes) {
nextNode = new NullNode();
prevNode = new NullNode();
}
}
}
public class NullNode extends Node
{
NullNode() {
super(false);
}
}
To call one constructor from another constructor use this(args)... you cannot call it directly

Related

Tree-Structure does not inherit generics

My goal is to create a tree-like object structure.
For this i created a class named Node (I removed the implementation because the problem still persists without it):
public class Node<S> {
public Node<S> addChild(Node<S> node) {
return this;
}
}
Important to know is that i want to define the generic type S only in the root node, all child nodes should automatically inherit from the root node.
Something like this:
new Node<String>().addChild(
new Node<>().addChild(
new Node<>()
)
)
I restricted the addChild method to only accept Nodes with the same generic type S,
so as far as i know my child node should know that it's generic type S has to be (in this example) String. However it seems like the generic type S gets lost after instantiating a new Node, because it gives me the following Exception:
error: incompatible types: Node<Object> cannot be converted to Node<String>
The use of <> requires type inference, and the argument of the first
addChild must be a Node, and just passing new Node<>() would do - infering from the return type.
But chaining to .addChild(new Node<>()) cannot infer anything, can only provide Node<Object>. So: one cannot use <>.
The problem is (of course) that you want addChild to return the head of the list, and keep adding to the tail of the list.
Normal practice is not to create Node instances, but just use the S values.
public class Node<S> {
private S value;
private Node<S> next;
public Node(S value) {
this.value = value;
}
public static <T> void print(Node<T> root) {
if (root == null) {
System.out.println("empty");
return;
}
System.out.print(root.value);
System.out.print(" --> ");
print(root.next);
}
public static <T> Node<T> addAll(T... values) {
Node<T> root = null;
Node<T> previous = null;
for (T value : values) {
Node<T> current = new Node<>(value);
if (root == null) {
root = current;
} else {
previous.next = current;
}
previous = current;
}
return root;
}
public static void main(String[] args) {
Node<String> root = Node.addAll("a", "b", "c", "d");
print(root);
}
}
Comparable to Collections.addAll or List.of. If you keep a Node<S> last field, you could indeed create something like:
public void addLast(S value) {
last.next = new Node<>(value);
}
This also shows a serious problem of the class: an empty list is not a Node.
One could use Optional<Node<S>> or a special constant for an empty list EMPTY - without value.
The normal solution is to have a container:
public class List<S> {
private class Node {
...
}
private Node<S> root;
private Node<S> last;
private int size;
public List<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return this;
}
private int size() {
return size;
}
...
}
Now everything fits.
List<String> nodes = new List<>()
.addLast("a")
.addLast("b")
.addLast("c")
.addLast("d");
After feedback, when wanting Node references.
Then discard chaining, and make Node public again.
public Node<S> addLast() {
addLast(null);
}
public Node<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return last;
}
List<String> nodes = new List<>()
Node<String> a = nodes.addLast();
Node<String> b = nodes.addLast();
var c = nodes.addLast();
var d = nodes.addLast();
One could use var for shortness.
What you are trying to do is something like this
public class Node<T> {
private Node<T> child;
private T data = null;
public Node (T data) {
this.data = data;
}
public T getData() {
return data;
}
public Node<T> getChild() {
return child;
}
public void addChild(Node<T> child) {
this.child = child;
}
#Override
public String toString() {
return "this node's data: " + data + "; has child? " + (child != null);
}
public static void main(String[] args) {
Node<String> root = new Node<> ("parent");
Node<String> child = new Node<>("child");
root.addChild(child);
System.out.println(root);
System.out.println(child);
}
}
If you were to execute this, it will output
this node's data: parent; has child? true
this node's data: child; has child? false
this node's data: 0; has child? false
this node's data: 1; has child? false
Notice how I can create nodes of type String and Integer. However, this class is incomplete if you want to create a tree structure. The implementation of "tree" will depend on what kind of tree you are talking about. For example, a simple binary tree will have two children at most. Other types of trees could have more children. Also, adding nodes to a tree might require balancing the tree.
Now, to your question, this answer suffices. I was able to demonstrate the use of generics to create Node objects of type T.

Type T is not a valide Substitute for the bounded Parameter `<T extends Collection<?>>

package einfuehrung.knodenUndListeKopie;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class List<T> {
private class ListIterator<K> implements Iterator<T> {
private Node<T> node = null;
public ListIterator() {
node = head;
}
#Override
public boolean hasNext() {
return node.getNext() != null;
}
#Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
node = node.getNext();
T obj = node.getObject();
return obj;
}
}
public Iterator<T> iterator() {
ListIterator<T> iter = new ListIterator<T>();
return iter;
}
private Node<T> head;
public List() {
this.head = new Node<T>();
}
public Node<T> getHead() {
return head;
}
public void setHead(Node<T> head) {
this.head = head;
}
public boolean isEmpty() {
return head.getNext() == null;
}
public void addFirst(T element) {
Node<T> node = new Node<T>();
Node<T> nextNode = head.getNext();
node.setObject(element);
node.setNext(nextNode);
head.setNext(node);
}
public void addLast(T element) {
Node<T> node = new Node<T>();
Node<T> lastNode = head;
while (lastNode.getNext() != null) {
lastNode = lastNode.getNext();
}
lastNode.setNext(node);
node.setNext(null);
node.setObject(element);
}
public Object removeFirst() {
Object solution;
if (isEmpty()) {
solution = null;
}
Node<T> node = head.getNext();
Node<T> nextNode = node.getNext();
solution = node.getObject();
head.setNext(nextNode);
return solution;
}
public Object removeLast() {
Object solution;
if (isEmpty()) {
solution = null;
}
Node<T> beforeLastNode = head;
Node<T> lastNode;
while (beforeLastNode.getNext().getNext() != null) {
beforeLastNode = beforeLastNode.getNext();
}
lastNode = beforeLastNode.getNext();
solution = lastNode.getObject();
beforeLastNode.setNext(null);
return solution;
}
/**
* It does not delete the node, where the element is saved.
*
* #return first element of list
*/
public Object getFirstElement() {
return head.getNext().getObject();
}
}
First above is my List-Class.
package einfuehrung.knodenUndListeKopie;
import java.util.Collection;
public class Node<T extends Collection<?>> {
private Node<T> next;
private T object;
public Node() {
}
public Node(Node<T> next, T object) {
this.next = next;
this.object = object;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
public T getObject() {
return object;
}
public void setObject(T object) {
this.object = object;
}
public int countAllElements() {
int solution;
solution = object.size();
if (this.next != null) {
solution += this.next.countAllElements();
}
return solution;
}
}
Second Class is my Node-Class.
Problem Description. Everything was fine after i restricted the Parameter T in my Node Class. I had to, because T needed to implement the size-Method. It was necessary for the countAllElements() Method in Node-Class. In my List Class i get the error message : "Type T is not a valide Substitute for the bounded Parameter <T extends Collection<?>> of the type Node<T>. The error message appears everywhere where i use an instance of my object from the type Node<T>.
I hope i did everything Right in this Question by Posting my Code here. Sorry for my case-shift, i live in Germany. I dont know what my Computer does D:.
Edited: Sorry guys, i forgot to Change the title. I adjusted it.
As it stands, you are contradicting yourself: you are saying that your Nodes can contain any T in your List class, but your Node class says they can contain any Collection.
So, you either need to:
Go through all of the Node<T>s in the List class, replacing them with something list Node<Collection<T>>, Node<List<T>> etc
Remove the bound on the type parameter in the Node class, and supply a ToIntFunction<? super T> to the countAllElements method, to allow you to say "this is how you 'count' a T":
public int countAllElements(ToIntFunction<? super T> counter) {
int solution = counter.apply(object);
if (this.next != null) {
solution += this.next.countAllElements(counter);
}
return solution;
}

Trouble using compareTo() with generics and a LinkedList and sort

I'm trying to create a SortedList class that extends a LinkedList class, only difference between the two is the SortedList has a method to insert whatever its holding in order.
public class SortedList<T> extends LinkedList<T> implements Iterable<T> {
// Class variables and constructor
public void insert(T objectToAdd){
Node<T> newNode = new Node<>(objectToAdd);
Node<T> currentNode = head.getNext(); // Head node is a single sentinel node, so we always need to start comparing from its next.
if (objectToAdd.compareTo(currentNode.getPayload()) == -1){
// Insert and setup node links.
} else if (... rest of here){
}
}
Problem I'm having is using the compareTo gives this error:
http://puu.sh/vxKxv/c9ee91d54c.png
Here is the Node class.
public class Node<T>{
// Class Variables
private final T data;
public int index;
private Node<T> next;
private Node<T> prev;
public Node(T data) {
this.payload = payload;
this.next = null;
this.prev = null;
}
public void setNext(Node<T> newNode) {
this.next = newNode;
}
public void setPrev(Node<T> newNode) {
this.prev = newNode;
}
public Node<T> getNext() {
return this.next;
}
public Node<T> getPrev() {
return this.prev;
}
public T getData() {
return this.data;
}
}
If you need me to post any of the other classes let me know.
Been stuck on this for awhile now, anyone able to help?
T is not a concrete type, hence compiler knows only that it has objects defined in Object class. If somebody makes the SortedList it will not have compareTo method, hence it cannot work. You need to make sure that T will contain the compareTo method. The easiest way is
public class SortedList<T extends Comparable> extends LinkedList<T> implements Iterable<T> { ... }
Also in my opinion it is better to check
if (objectToAdd.compareTo(currentNode.getPayload()) < 0) { ... }
because it gives you the relation that objectToAdd < currentNode.getPayload() visually. Also Comparable interface gives no guarantee it will be -1. It says:
#return a negative integer, zero, or a positive integer as this object
is less than, equal to, or greater than the specified object.

Linked List using generics, getting "not applicable arguments for parameters" error

My Node class:
public class Node<T>
{
protected T data;
protected Node<T> next;
protected Node<T> previous;
public Node()
{
this.data = null;
this.next = null;
this.previous = null;
}
public Node(T data)
{
this.data = data;
this.next = null;
this.previous = null;
}
public Node(T data, Node<T> next, Node<T> previous)
{
this.data = data;
this.next = next;
this.previous = previous;
}
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
public Node<T> getNext()
{
return next;
}
public void setNext(Node<T> next)
{
this.next = next;
}
public Node<T> getPrevious()
{
return previous;
}
public void setPrevious(Node<T> previous)
{
this.previous = previous;
}
}
My LinkedList class:
public class LinkedList<T extends Node<T>>
{
private Node<T> head;
private Node<T> tail;
private Node<T> currNode;
public LinkedList()
{
head = null;
tail = null;
currNode = null;
}
public LinkedList(Node<T> head)
{
this.head = head;
tail = head;
currNode = head;
}
public void resetHead()
{
currNode = head;
}
public void add(T data)
{
Node<T> newNode = new Node<T>(data);
newNode.next = null;
if(head == null)
{
head = newNode;
}
else
{
tail.next = newNode;
newNode.previous = tail;
tail = newNode;
}
}
public void addHead(T data)
{
Node<T> newNode = new Node<T>(data);
newNode.next = head;
head.previous = newNode;
head = newNode;
}
public void addAfter(T data, Node<T> previousNode)
{
Node<T> newNode = new Node<T>(data);
newNode.next = previousNode.next;
previousNode.next = newNode;
}
public void addBefore(T data, Node<T> nextNode)
{
Node<T> newNode = new Node<T>(data);
newNode.next = nextNode;
nextNode.previous = newNode;
}
public void delete(Node<T> nodeToDelete)
{
(nodeToDelete.getNext()).setPrevious(nodeToDelete.getPrevious());
(nodeToDelete.getPrevious()).setNext(nodeToDelete.getNext());
nodeToDelete.setNext(null);
nodeToDelete.setPrevious(null);
}
public boolean hasNext()
{
if(head == null)
{
return false;
}
else if(currNode.next != null)
{
currNode = currNode.getNext();
return true;
}
else
{
return false;
}
}
public boolean hasPrevious()
{
if(tail == null)
{
return false;
}
else if(currNode.previous != null)
{
currNode = currNode.getPrevious();
return true;
}
else
{
return false;
}
}
public Node<T> getHead()
{
return head;
}
public void setHead(Node<T> head)
{
this.head = head;
}
public Node<T> getTail()
{
return tail;
}
public void setTail(Node<T> tail)
{
this.tail = tail;
}
public Node<T> getCurrNode()
{
return currNode;
}
public void setCurrNode(Node<T> currNode)
{
this.currNode = currNode;
}
}
The error crops up when attempting to use any of the add/insert methods in LinkedList. For example, if I try to use the add(T data) method, like so: listOfChars.add('B');, I get the following error: The method add(Node) in the type LinkedList is not applicable for the arguments (char). What I expect it to do is to accept the data (in this case, the char 'B'), create a new node with 'B' as the data, and then put it in the linked list after the last node in the list. From my understanding, the method is expecting a Node instead of any generic data type, such as a char.
After doing some researching, I think somewhere in my TestLinkedList class, I have declared the LinkedList object incorrectly:
public class TestLinkedList
{
public static void main(String[]args)
{
Node<Character> n1 = new Node<Character>('A');
LinkedList listOfChars = new LinkedList(n1);
listOfChars.add('B');
}
}
but I can't figure out how to declare it correctly. I've tried LinkedList<Character>, LinkedList<Node>, LinkedList<Node<T>>, and LinkedList<Node<Character>>, but none of them are correct. Any help would be appreciated as this is my first time using generics and I am just trying to learn how to apply it to a Linked List I've made.
You need to fix two things. First, the class declaration of LinkedList says:
public class LinkedList<T extends Node<T>> {
which means that T has to be both a Node and the element of a Node. This doesn't work with Character since a Character is not an instance of Node. If you remove the constraint so that T can be any value, it works with Character.
public class LinkedList<T> {
Next you should add the generic part to the main file for the listOfChars as well:
LinkedList<Character> listOfChars = new LinkedList<Character>(n1);
Also make sure that you have imported the right LinkedList and not the java standard class.
You simply have to rewrite LinkedList from
LinkedList<T extends Node<T>>
to
LinkedList<T>
since in the code of LinkedList you already state that you are using Node objects.
You can use it like this:
public static void main(String[]args)
{
Node<Character> n1 = new Node<>('A');
LinkedList<Character> listOfChars = new LinkedList<>(n1);
listOfChars.add('B');
}
I think its a combination of both Todd's and Adams answer
public class LinkedList<T extends Node<T>>
to
public class LinkedList<T>
and
LinkedList<Character> listOfChars = new LinkedList<>(n1);
As you can infer from the error The method add(Node) in the type LinkedList is not applicable for the arguments (char)
This is a type error, your add method expects a Node but in the main you call add with type character.
Your LinkedList class is expecting an object of type T extends Node. Which would imply a custom class that extends your Node object, however that is not what you are looking to use to add objects to the linkedlist.
Ok, so your class declaration
public class LinkedList<T extends Node<T>>
is saying 'This is a class LinkedList parameterised by T where T is a subtype of Node<T>
This means if you wanted T = Character for example, you would need Character to be a subtype of Node<Character>, which doesn't really make sense.
You probably want to just parameterise your class by T eg public class LinkedList<T>
Then you can go LinkedList<Character> listOfChars = new LinkedList<Character>(n1)
or more succinctly LinkedList<Character> listOfChars = new LinkedList<>(n1) as the second generic parameter can be inferred
Create your LinkedList like this:
LinkedList<Character> listOfChars = new LinkedList<>(n1);
EDIT:
M4ver1k is right that this alone won't fix it. I missed the part that Adam Arold pointed out. Adam's answer fixes the problem and should be accepted. My answer just prevents the LinkedList from being implicitly defined as a LinkedList<Object>.
.

Iterative approach to BST

these are my fields:
public class BSTSet <E> extends AbstractSet <E> {
// Data fields
private BSTNode root;
private int count = 0;
private Comparator<E> comp; // default comparator
/** Private class for the nodes.
* Has public fields so methods in BSTSet can access fields directly.
*/
private class BSTNode {
// Data fields
public E value;
public BSTNode left = null;
public BSTNode right = null;
// Constructor
public BSTNode(E v) {
value = v;
}
//creates a method called contains so that i can call it later on for my find method
public boolean contains(Object item) {
return contains(item);//root.value.equals(item);
}
public int height() {
return height();
}
}
// Constructors - can either use a default comparator or provide one
public BSTSet() {
comp = new ComparableComparator(); // Declared below
}
public BSTSet(Comparator <E> c) {
comp = c;
}
}
and this is what i am trying to complete:
private class BSTSetIterator implements Iterator<E> {
private Stack<BSTNode> stack = new Stack<BSTNode>();
private BSTNode current = root;
public BSTSetIterator(BSTNode root) {
return new BSTSetIterator();
}
public boolean hasNext() {
boolean hasNext = false;
hasNext = !stack.isEmpty() || current != null;
return hasNext;
}
public E next() {
BSTNode next = null;
while (current != null) {
stack.push(current);
current = current.left;
}
next = stack.pop();
current = next.right;
return next;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
// Comparator for comparable
private class ComparableComparator implements Comparator<E> {
public int compare(E ob1, E ob2) {
return ((Comparable)ob1).compareTo(ob2);
}
}
So far the code fails at lines return new BSTSetIterator(); and return next;. For return next it says that it is the wrong data type to return. How would I go about fixing these methods so that I can iterate through a BST using a Stack?
BSTSetIterator();
This doesn't work, because your constructor expects a root and you didn't pass that parameter. If you have a BSTSet object called 'tree', and you want to create a new iterator, then you should create the iterator this way:
BSTSetIterator iterator = new BSTSetIterator(tree.getRoot());
However, you don't have a getter in your BSTSet class and your root is private. Don't worry, the solution for that problem is to create a public getter inside your BSTSetIterator class, like this:
public BSTNode getRoot()
{
return this.root;
}
Constructors don't return values, this is incorrect:
public BSTSetIterator(BSTNode root) {
return new BSTSetIterator();
}
Instead, write your construtor this way:
public BSTSetIterator(BSTNode root)
{
this.current = root;
}
Also, this definition is incorrect, because root is out of reach:
private BSTNode current = root;
You should have this instead:
private BSTNode current;
As for your other problem,
BSTNode next = null;
means that your variable called 'next' is of BSTNode type.
public E next()
means that your method called next is of E type. as E and BSTNode is not the same, your return:
return next;
is incorrect. I could give you more help, but I have realized you are learning now the language and it's better to let you explore yourself the technology and programming in general, because this way you will become quicker. "Give a man a fish, and you feed him for a day. Teach a man how to fish, and you feed him for a lifetime."

Categories

Resources