Incompatible Types with Generics - java

I am unfamiliar with generics, so in this method here where i'm trying to implement a remove method from scratch, :
public class LinkedList<T> implements LinkedListInterface<T> {
private Node head;
private Node tail;
private int count;
public LinkedList () {
head = null;
tail = null;
count = 0;
}
class Node {
T data;
Node next;
Node(T data) {
this.data = data;
next = null;
}
}
public Node getHead() {
return head;
}
public T remove(int pos) throws ListException {
if (pos < 1 || pos > count) {
throw new ListException("Invalid position to remove from");
}
Node removedItem = null;
if (count == 1) {
removedItem = head;
head = null;
tail = null;
}
else if (pos == 1) {
removedItem = head;
head = head.next;
}
else if (pos == count) {
removedItem = tail;
Node prev = jump(pos - 2);
prev.next = null;
tail = prev;
}
else {
Node prev = jump(pos - 2);
removedItem = prev.next;
prev.next = prev.next.next;
}
count--;
return removedItem; // error: incompatible types: LinkedList<T>.Node cannot be converted to T
}
}
I need help identifying what this 'T' is exactly in the remove method and what this error message means and what I should do to fix it, thanks for the help

Generics (or rather, the proper name, 'type variables') is a way to link things.
All Ts represent a type. Everyplace T is mentioned, it's the same type for any given 'usage' of a thing, but you don't know what T is. It could be Number, it could String, it could SomethingYouNeverHeardAbout. But it's some type or other. If you did know, you'd just write that out instead.
In your snippet, public LinkedList<T> declares the type variable (just like you need to type int x; before you can start using x as a variable that can hold values, you need to declare a type variable, and that's where it is declared. T has no restrictions - it can be any type (except primitives, because primitive types and generics don't mix at all, at least, for now - maybe future java versions change this).
All other occurrences of T in the entire file are simply usages of it.
In other words, your code says: For any specific LinkedList, it has some type associated with it. We have no idea what it is, but every instance has such a thing.
Generics are entirely a compile time affair so this has no effect whatsoever when you run the code, it's solely for the compiler to help you out and tie things together. The point of the exercise is simply to let you tell the compiler that various types used in different places are unknown, but we do know, they are the same.
So, given any particular instance of LinkedList, its remove method returns the same type that its add method receives. Which is the same type as the data field of its internal Node inner class.
What does this get you? Compile-time checking, for one. The compiler can now find bugs for you. And so it has! Your intent is clearly for the remove method to return the thing it removed, but you aren't doing that. You are actually returning the node object that contains the thing you removed. This node object isn't even publicly visible (your Node internal class has package private access), clearly completely useless to return that, and as per your signature, you didn't mean to.
To fix your bug, just write return removedItem.data; instead.

Related

Singly Linked List pass by value

Hi i am learning linked list in java. Its a simple doubt but couldn't figure out.
class Node{
int data;
Node next;
Node(int data){
this.data = data;
this.next = null;
}
//java main method
Node head = null;
Node newNode = new Node(1);
head.next = newNode;
Here i am passing the reference of the newNode to the next field in the Node class. The next is holding the reference of the newNode.
In dart programming languages objects are passed via call by value. By doing the above code is also working fine. My question is can we implement the Node field inside the Node class with either by reference or value.
In the context of c++, I don't know much c++ syntax but roughly it looks like this
//with pointer
class Node{
public:
int data;
Node* next;
}
It is possible to implement the above code like this one
//without pointer
class Node{
public:
int data;
Node next;
}
As stated by the other answers, your code wont work since your head variable is null and thus would throw a NullPointerException.
Your main method should like this:
Node head = new Node(0);
Node newNode = new Node(1);
head.next = newNode;
Java is always passing references by value. For a comprehensive answer see https://stackoverflow.com/a/40523/19799529
Pass-by-value
Java is always passing by value (as you are accustomed to):
int x = 3; f(x);
Object y = new Object(); g(y);
Above neither f nor g can alter the passed variables x and y.
The variables are just memory slots in which the value is stored, and that value is passed (not which memory slot), whether primitive type (int) or class instance (Object).
Linked list
Your Node class is fine.
public class SingleLinkedList {
Node head;
int count;
public int size() {
return count;
}
It is worth holding the Node inside a list class, possibly with a field for the number of elements. You could use that for index checking.
public void add(int i, int data) {
head = addToNodes(head, i, data);
++count;
}
private Node addToNodes(Node link, int i, int data) {
if (i <= 0 || link == null) {
Node node = new Node(data);
node.next = link;
return node;
}
link.next = addToNodes(link.next, i - 1, data);
return link;
}
Above I have used a recursive method. It shows that as the passed variable (head or some node's next field) cannot be changed in java, one has to return it assigning it to the same variable.
The code above is not very nicely formulated; write your own logic.

Constructor Node cannot be applied to given types while working with nodes

I am working on a code that puts new elements on MyStack if they are unique. I had to copy and paste the node starting code, so I'm having a bit of trouble with an issue. I keep getting two error messages, even after trying various workarounds and I'm not really understanding why. I've even tried using some helper functions I've previously made that have worked before so I'm extra confused.
The two errors I consistently get are:
-cannot infer type arguments for MyStack.Node (actual and formal arguments differ in length)
-constructor node cannot be applied to given types. Required, no arguments, found: anything,
Here's my code:
public class MyStack<Anything>
{
private Node first, last;
private class Node<Anything>
{
Anything item;
Node next;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
public void add(Anything value)
//method that adds a new value to the end of the list
//COMPLETE
{
Node temp = first;
while(temp.next!=null){ //finds the end
temp=temp.next;
}
temp.next=new Node(value, null); //assigns new value
}
public void enqueue(Anything info){
if (this.contains(info)==true) { //if the info is already present
System.out.println("the stack already contains this value");
return;
}
//if we actually need to add the info
if (first == null) { //if there is nothing in the stack
Node temp= first;
first = new Node<>(info,temp);
first = temp;
return;
}
if (first != null) { //if there is already stuff
Node temp = first;
while (temp.next == null)
{ Node newNode= new Node<>(info, temp);
temp.next = newNode;
}
return;
}
}
}
As #Andreas already pointed out, Node needs a constructor.
There are a few other flaws in your Code:
Use Generics
With your Code, you can only store Objects of the class Anything, what strongly limits its reusability. Use a generic instead and you can reuse this class for many more purposes.
Linked List
I suggest, you use the paradigm of a double-linked-list. That way you do not need to find the last Node to add something to the Stack. Node now has a pointer to its previous and next element.
Use the last Object
You have the object last but never use it. To find out, whether the current object is the last one you compare the value to null. This has the effect, that storing a null value will break your List. Instead compare to the Object last, this object is unique and guarantees you, that you are at the end of the list. Both first and last are Nodes that do not contain a value and are simply used to mark the start/end of your List.
Adding elements
Using the changes above, the code in the Method enqueue(T value) becomes significantly simpler: You just check whether contains(value) and decide whether you add the value to the List or not.
All these changes applied result in following code:
public class MyStack<T extends Object> {
private Node first, last;
public MyStack() {
first = new Node(null, null, null);
last = new Node(null, null, first);
first.next = last;
}
private class Node {
T item;
Node next;
Node previous;
public Node(T item, Node next, Node previous) {
this.item = item;
this.next = next;
this.previous = previous;
}
}
public boolean contains(T value) {
for (Node curr = first.next; curr != last; curr = curr.next) {
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
/**
* method that adds a new value to the end of the list
*/
public void add(T value)
{
Node secondLast = last.previous;
Node added = new Node(value, last, secondLast);
secondLast.next = added;
last.previous = added;
}
/**
* only adds value if it is not already contained by the Stack
*/
public void enqueue(T value) {
if (this.contains(value) == true) { // if the info is already present
System.out.println("the stack already contains this value");
}
else {
add(value);
}
}
public static void main(String[] args) {
MyStack<String> test = new MyStack<>();
test.add("foo");
test.add("bar");
test.add("baz");
System.out.println(test.contains("bar"));
System.out.println(test.contains("new"));
test.enqueue("baz");
test.enqueue("MyStack");
}
}
Naming
As you may have noticed, in my explanation I called this class a List. This is because it fulfills more of the characteristics of a List. A Stack usually only provides the methods push to put something at the top of the Stack and pop to remove and return the topmost Object. Optionally peek can return the topmost Object, without removing it from the Stack.
Also consider renaming the method enqueue: enqueue is used in Queues (obviously) and Queues do not forbid to add two equal Objects. So the name is misleading. I would call this method something like addIfNotContaining.
In my Opinion you should name this class to be a List and add a method get(int i) to get a specific element at a position. Naturally adding some other methods like size ect. to comply with a standard List. But I assume you already had, but did not post them because they are not related to your problem.
Multithreading
This Class is far from threadsave. But I let you figure out yourself how to make it threadsave if needed.

How to use Comparable as a Generic parameter in a Class

I have a home work in a data structures course, the question is:
Implementation of doubly-linked list class.
the methods:
display()
length() or size()
insertSorted(Comparable)
insertToEnd(Comparable)
insertToHead(Comparable)
delete(Comparable)
boolean search(Comparable)
You must do this in JAVA
Create an application layer to test your class and its methods.
Compress all of your source files into a file and rename it as CS214HW1_first_lastName.zip Put your name in the filename. If needed, add a ReadMe.txt file for extra information such as compilation.
I implemented everything correctly and the code is working fine, but I used for example: insertSorted(int) instead of insertSorted(Comparable), because I didn't know how to do it.
I searched online, and read the JAVA documentation for (Comparable) but it is not enough :(
Can anybody help, please it is very important?
Here's some of my code, I can't write it all, cuz I don't want my friends to get the same code.
I will take zero if there is same code.
Code:
class DLL {
class Node {
Node next;
Node prev;
int data;
Node() {
next = null;
prev = null;
data = 0;
}
Node(int dt) {
next = null;
prev = null;
data = dt;
}
}
Node head;
void insertToHead(int dt) {
if (head == null) {
head = new Node(dt);
}
else {
head.prev = new Node(dt);
head.prev.next = head;
head = head.prev;
}
}
public static void main(String args[]) {
DLL dll = new DLL();
dll.insertToHead(1);
dll.insertToHead(2);
dll.insertToHead(3);
}
}
Please, somebody, tell me what to change in the beginning of the class.
are we gone use extends or implements Comparable<E> or what!
and what changes should i do the method insertToHead(Comparable)
what changes should i do to the main.
You would probably like to look into how generics work as well. The basic idea is that you would like to set up your class so that it will not know exactly the specific type of object but can be given some hint at the types of things it can expect of a declared generic type.
In your case, you would like to set up your list so that you can create linked lists of anything that can be compared. Java has a class for that which you have mention called Comparable<E> this tells Java that it will be able to call such methods as compareTo on the provided object.
More specifically to your closing questions:
Use the following style of class declaration MyClass<MyGenericType extends Comparable<MyGenericType>>. In your case DLL<E extends Comparable<E>>.
Switch the method arguments to accept E our declared generic type.
You should use the class Integer instead of the primitive type int, and change the creation of your list to DLL<Integer> dll = new DLL<Integer>().
Fully updated version of provided code:
public class DLL<E extends Comparable<E>> {
class Node {
Node next;
Node prev;
E data;
Node() {
next = null;
prev = null;
data = null;
}
Node(E dt) {
next = null;
prev = null;
data = dt;
}
}
Node head;
void insertToHead(E dt) {
if (head == null) {
head = new Node(dt);
}
else {
head.prev = new Node(dt);
head.prev.next = head;
head = head.prev;
}
}
public static void main(String args[]) {
DLL<Integer> dll = new DLL<Integer>();
dll.insertToHead(1);
dll.insertToHead(2);
dll.insertToHead(3);
}
}
This new implementation should provide a hint for how to proceed with some of the other homework tasks. For instance you can now compare objects just by their compareTo method which might useful for sorting hint hint.
That doc page gives a very good explanation for how to use this method. You should note that in their docs, they use a generic type called T instead of E, it really doesnt make a difference you can call it whatever you want provided it is unique to your program.
Edit:
An each hint in the sorting direction:
Ojbects which extend the Comparable class have a method which is called compareTo this method is set up so you can call:
object1.compareTo(object2);
this method returns an int which will be:
> 0 when object1 is greater than object2
= 0 when object1 is equal to object2
< 0 when object1 is less than object2
I don't want to give away too much as this is a homework assignment but here is my hint:
The way the above code sets up your classes, you would be able to tell the relationship between NodeA and NodeB by calling:
NodeA.data.compareTo(NodeB.data)
this will return an integer which gives your information according to the list above.
The <=,>=,== operators are likely found in the Integer class's compareTo method.
Something like:
public int compareTo(Object o) {
int otherNumber = ((Integer) o).intValue();
int thisNumber = this.intValue();
if (otherNumber > thisNumber) {
return 1;
} else if (otherNumber < thisNumber) {
return -1;
} else {
return 0;
}
}
but more likely they just do something like:
public int compareTo(Object o) {
return this.intValue() - o.intValue(); // possibly normalized to 1, -1, 0
}
See the Docs on Integer for more info on this.

Two objects refer to each other with final references

I have a class that looks something like this:
public class Node {
private final Node otherNode;
public Node(Node otherNode) {
this.otherNode = otherNode;
}
}
and want to do something like
Node n1, n2 ;
n1 = new Node(n2);
n2 = new Node(n1);
but obviously cannot since n2 is not initialized yet. I don't want to use a setter to set otherNode because it's final, and thus should only be set once ever. What is the cleanest approach to accomplishing this? Is there some fancy Java syntax I'm unfamiliar with to let me do this? Should I use an initialize method in addition to the constructor (ugly), or just cave and use a setter (also ugly)?
Have a second constructor that takes no parameters and constructs its own Node, passing itself as the other's "other".
public class Node
{
private final Node otherNode;
public Node(Node other)
{
otherNode = other;
}
public Node()
{
otherNode = new Node(this);
}
public Node getOther()
{
return otherNode;
}
}
Then when using it:
Node n1 = new Node();
Node n2 = n1.getOther();
Assuring that they refer to each other:
System.out.println(n1 == n1.getOther().getOther());
System.out.println(n2 == n2.getOther().getOther());
System.out.println(n1 == n2.getOther());
System.out.println(n2 == n1.getOther());
These all print true.
(This is a supplement to rgettman's answer.)
A more general solution is to write a constructor like:
private Node(final int numNodesInLoop) {
if(numNodesInLoop < 1) {
throw new IllegalArgumentException();
}
Node head = this;
for(int i = 1; i < numNodesInLoop) {
head = new Node(head);
}
this.otherNode = head;
}
Your case, with two nodes, would be instantiated as new Node(2).
I made the above private, per a comment by user949300 to rgettman's answer, because the meaning of a Node constructor that takes an int is not very guessable (it creates a loop?!), so it's better to wrap it in a static factory method whose name makes its functionality clear:
public static Node newNodeLoop(final int numNodes) {
return new Node(numNodes);
}
(This is also more future-proof in case you later have a need for another constructor that would take an int, for whatever reason. You can then modify this constructor to take a dummy argument as well, just enough to tell the compiler what constructor you want. The factory method would still have the same contract.)

Java Pass by value, Advantage or Disadvantage?

Java is pass by value. What if I need a pass by reference. For example in the following code I need a pass by reference mechanism.
public class BinaryTree {
public TreeNode root;
public BinaryTree(){
root = null;
}
public TreeNode insert(TreeNode temp,int x){
if(temp == null){
temp = new TreeNode();
temp.key = x;
temp.left = temp.right = null;
return temp;
}
if(temp.key > x)
temp.left = insert(temp.left,x);
else if(temp.key < x)
temp.right = insert(temp.right,x);
return null;
}
}
When insert is called with root, I need root to be passed as a reference so as to change its value. But this does not happen in Java, since it's pass by value. In C/C++ the above could be easily achieved. Don't you think that this is a drawback of Java? How could such problems be solved in Java?
In Java, if you have a reference type the reference is passed by value.
Inside the method you can mutate the object that was passed and the caller will see those changes.
Don't you think that this is a drawback of Java?
No. Because:
There are few cases where you really need it.
There are workarounds (see below).
Implementing pass by reference in Java would be difficult. It makes code generation and garbage collection significantly more complicated.
(OK ... so really these are counter-arguments. But we are talking about a language design issue here, and any rational discussion of language designs has to weigh up the pros and cons of supporting a particular feature. And that includes implementation cost and performance issues.)
How could such problems be solved in Java?
The general approach is to restructure your code so that the variable you need to update in the called method is replaced with a reference to a mutable object or an array. This may entail the caller doing a bit more work, but that is generally acceptable.
Alternatively (and in your example) restructure the code so that call by reference is unnecessary.
In your example, there are two observations to make:
The "call-by-reference" mechanism is only used in the case where the tree is empty. It is not difficult to change this so that it is not necessary.
In fact, your use of call-by-reference, and in fact the entire insert method, is a leaky abstraction. There is nothing to stop you calling the method with a node object that is nothing to do with the current BinaryTree instance. You are relying on the caller to maintain the (implied) invariants of the tree.
The following version addresses both of these issues:
public class BinaryTree {
private static class TreeNode { ... }
public TreeNode root;
public BinaryTree(){
root = null;
}
public void insert(int x) {
root = insert(root, x);
}
private TreeNode insert (TreeNode node, int x) {
if (node == null) {
return new TreeNode(x);
}
if (node.key > x)
node.left = insert(node.left, x);
else if (node.key < x)
node.right = insert(node.right, x);
return node;
}
}
(I don't exactly like the way that we reassign the left / right pointers at each level after the insertion, but it does make the insertion logic simple.)
root can be changed by getting the return value.
public void insert(int x) {
root = insert(root, x);
}
I changed the method insert(...) a little.
private TreeNode insert(TreeNode temp,int x){
if(temp == null){
temp = new TreeNode();
temp.key = x;
temp.left = temp.right = null;
}
if(temp.key > x)
temp.left = insert(temp.left,x);
else if(temp.key < x)
temp.right = insert(temp.right,x);
return temp;
}
Java is pass by value for everything. Whether you are working with primitives or with reference types.
The "value" or a reference type is the reference itself, so when using reference types the reference itself is passed.

Categories

Resources