I can´t override toString Method [duplicate] - java

This question already has an answer here:
Java generics - The type parameter String is hiding the type String
(1 answer)
Closed last month.
Hello I have two java classes "List" and "ListPlayground". The problem is i can´t override the toString() Method, because I get this Error:
error: toString() in List cannot override toString() in Object
public String toString() {
^
return type String is not compatible with java.lang.String
where String is a type-variable:
String extends Object declared in class List
List.java:59: error: incompatible types: java.lang.String cannot be converted to String
String string = "";
^
where String is a type-variable:
String extends Object declared in class List
Note: List.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors
Here is the class I have
public class List<String> {
private class Node {
private String element = null;
private Node next = null;
private Node(String element, Node next) {
this.element = element;
this.next = next;
}
private Node(String element) {
this.element = element;
}
}
private Node head = null;
private Node current = head;
public void prepend(String object) {
head = new Node(object, head);
}
public void append(String object) {
if(head == null) {
head = new Node(object);
return;
}
Node current = head;
while(current.next != null) {
current = current.next;
}
current.next = new Node(object);
}
public String first() {
get(0);
}
public String get(int index) {
Node current = head;
for(int i = 0; i < index; i++) {
current = current.next;
}
return current.element;
}
public int size() {
Node current = head;
int size = 0;
for(; current != null; size++) {
current = current.next;
}
return size;
}
public String toString() {
String string = "";
while(current != null) {
string += head.element + " -> ";
current = head.next;
}
return string;
}
}
Here is the ListPlayground class:
public class ListPlayground {
public static void main(String[] args) {
List<String> stringliste = new List()<>;
stringliste.append("World");
stringliste.append("!");
stringliste.prepend("Hello");
System.out.println("The Length of the List is: " + stringliste.size());
System.out.println("The first Element of the List is: " + stringliste.first());
System.out.println("The element with Index 2 is: " + stringliste.get(2));
System.out.println("The last element is: " + stringliste.get(stringliste.size() - 1));
System.out.println("The whole List is: " + stringliste.toString());
System.out.println("And again the whole List " + stringliste.toString());
}
}
can somebody help me?
I tried to debug my code but I did not succeed. I know that the class "Object" is the superclass of all classes and I have to override the toString() Method, but I do not understand why the toString() method is wrong i the List class?

It's because your generic type is called String, which is shadowing the java.lang.String class. They both extend the Object, but they are fundamentally different.
To fix this problem, call your generic argument something else.
i.e.:
public class List<T> {
private class Node {
private T element = null;
private Node next = null;
private Node(T element, Node next) {
this.element = element;
this.next = next;
}
private Node(T element) {
this.element = element;
}
}
private Node head = null;
private Node current = head;
public void prepend(T object) {
head = new Node(object, head);
}
public void append(T object) {
if(head == null) {
head = new Node(object);
return;
}
Node current = head;
while(current.next != null) {
current = current.next;
}
current.next = new Node(object);
}
public T first() {
get(0);
}
public T get(int index) {
Node current = head;
for(int i = 0; i < index; i++) {
current = current.next;
}
return current.element;
}
public int size() {
Node current = head;
int size = 0;
for(; current != null; size++) {
current = current.next;
}
return size;
}
public String toString() {
String string = "";
while(current != null) {
string += head.element + " -> ";
current = head.next;
}
return string;
}
}
or you could just specify which String you want to return in the toString() method
i.e.:
public java.lang.String toString() {
java.lang.String string = "";
while(current != null) {
string += head.element + " -> ";
current = head.next;
}
return string;
}
Generally I would prefer solution 1) over 2). It's never a good idea to introduce a generic parameter which shadows a class name.

When you use public class List<String>, "String" is used as a generic type and not java.lang.String.
You should change your class declaration and remove the type as you don't need it.
public class List {
... your code here
}
public class List<T> is same as public class List<String> and in both the cases, it is generic type and not a java.lang.String type.

A List<String> class is declared in the code, which syntactically is like declaring a List<T> class where the "T" is called "String."
So when you try to do the override the compiler is like seeing this:
public T toString()
Also in the implemation of the toString method it is very inefficient to use the +=, it uses a StringBuilder instead.

Related

Generic Methods for Linked-list

trying to get these 2 methods to work, but I don't have much experience with generics and the concept is confusing a lot.
Anything getFirst(): Returns the value stored in the first node in the list. It should print an error message and return null if the list is empty.
Anything getLast(): Returns the value stored in the last node in the list. It should print an error message and return null if the list is empty.
Here's my code: (The methods above appear at the bottom)
public class Node<Anything>{
private Anything data;
private Node next;
Node(Anything a, Node n)
{
data = a;
next = n;
}
public Anything getData()
{
return this.data;
}
public Anything setData(Anything newData)
{
Anything oldData = this.data;
this.data = newData;
return oldData;
}
public void setNext(Node newNext)
{
this.next = newNext;
}
public Node getNext()
{
return this.next;
}
}
-----------------------------------------------
public class CS2LinkedList<Anything>{
private Node first;
private Node last;
public CS2LinkedList()
{
first = null;
}
public boolean isEmpty()
{
return (first == null);
}
public void addFirst(Anything d)
{
Node temp = first;
first = new Node(d,temp);
}
public void clear()
{
first = null;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.getNext())
{
if (value.equals(curr.getData())){
return true;
}
}
return false;
}
public String toString()
{
StringBuilder result = new StringBuilder(); //String result = "";
for (Node curr = first; curr != null; curr = curr.getNext())
result.append(curr.getData() + "->"); //result = result + curr.data + "->";
result.append("[null]");
return result.toString(); //return result + "[null]";
}
public int size()
{
int size = 0;
for (Node curr = first; curr != null; curr = curr.getNext()){
size++;
if (first==null){
size = 0;
}
}
return size;
}
// ------------------------ Question begins here ------------------------
public Anything getFirst()
{
if (first != null){
// What should I return here? I tried returning first, (Anything) first, but none of them seems to work.
}
else{
return null;
}
}
public Anything getLast()
{
if (first != null){
// Same here
}
else{
return null;
}
}
The class Node has a type parameter, but in your class CS2LinkedList you are using it without the type parameter. You're using it as a raw type. Raw types only exist in Java for backward compatibility with very old Java versions, which didn't have generics. You shouldn't use raw types (unless absolutely necessary because you have to work with very old code).
Everywhere where you write Node in your class CS2LinkedList, write Node<Anything> instead. For example, declare the member variables like this:
private Node<Anything> first;
private Node<Anything> last;
Write your addFirst method like this:
public void addFirst(Anything d)
{
Node<Anything> temp = first;
first = new Node<>(d,temp);
}
Etcetera.
Then, in you can write your getFirst() method like this:
public Anything getFirst()
{
if (first != null){
return first.getData();
}
else{
return null;
}
}
And similar for the getLast() method.
You also need to modify some of the code in class Node. The constructor parameter and the parameter of the setNext method should also have a type argument:
Node(Anything a, Node<Anything> n)
{
data = a;
next = n;
}
public void setNext(Node<Anything> newNext)
{
this.next = newNext;
}
As well as the return type of the getNext method:
public Node<Anything> getNext()
{
return this.next;
}

I need help to write a program that takes input from user and reverses using a stack?

I’m trying to build a program (Java) that would take string input from user puts it into a stack and then reverses the stack using push and pop. When the user inputs “end-line” the program will stop pushing to the stack and print the strings entered by user in reverse order ?
public class stackReversal{
private class Node{
private String item;
private Node next;
}
private Node first = null;
public boolean isEmpty(){
return(first == null);
}
public void push(String s){
Node node = new Node();
node.item = s;
node.next = first;
first = node;
}
public String pop(){
if(first == null)
throw new RuntimeException("Stack Empty!");
String result = first.item;
first = first.next;
return result;
}
public String popString(){
String result="";
Node current = first;
while(current != null){
result += current.item;
current = current.next;
}
return result;
}
public static void main(String [] args)
{
stackReversal s = new stackReversal();
s.push("Hello");
s.push("world");
s.push("!");
System.out.println("Strings:" + s);
}
}
Please find the below code. All I did is I override the toString method to print the nodes item.
Now I am inputting 1,2,3 it will print Strings:3 -> 2 -> 1 as output.. Hope this helps
public class stackReversal {
private class Node {
private String item;
private Node next;
}
private Node first = null;
public boolean isEmpty() {
return (first == null);
}
public void push(String s) {
Node node = new Node();
node.item = s;
node.next = first;
first = node;
}
public String pop() {
if (first == null)
throw new RuntimeException("Stack Empty!");
String result = first.item;
first = first.next;
return result;
}
public String popString() {
String result = "";
Node current = first;
while (current != null) {
result += current.item;
current = current.next;
}
return result;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*
* This method prints the nodes in reerse order
*/
#Override
public String toString() {
StringBuilder nodes = new StringBuilder();
Node node = first;
while (node != null) {
nodes.append(node.item).append(" -> ");
node = node.next;
}
if(isEmpty()) {
return "";
} else {
return nodes.toString().substring(0, nodes.toString().length() - 4);
}
}
public static void main(String[] args) {
stackReversal s = new stackReversal();
s.push("1");
s.push("2");
s.push("3");
System.out.println("Strings:" + s);
}
}

What is a better method to sort strings alphabetically in a linked list that is reading in lines from a text file?

public class ContactList {
private ContactNode head;
private ContactNode last;
public ContactNode current;
public ContactList value;
public ContactList() {}
public void addNode(ContactNode input) {
if (this.head == null) {
this.head = input;
this.last = input;
} else last.setNext(input);
input.setPrev(last);
this.last = input;
}
public void traverse() {
System.out.println();
current = this.head;
while (current != null) {
System.out.print(current.getName() + " ");
System.out.println("");
current = current.getNext();
}
System.out.println();
}
public void insertNewFirstNode(String value) {
ContactNode newNode = new ContactNode(value);
head = newNode;
if (last == null) {
last = head;
}
}
public void sort() {
ContactList sorted = new ContactList();
current = head;
while (current != null) {
int index = 0;
if ((current.getName() != null)) {
index = this.current.getName().compareTo(current.getName());
if (index == 1) {
sorted.insertNewFirstNode(current.getName());
}
current = current.getNext();
} else if ((current != null)) {
System.out.print(sorted + "\n");
}
}
} // end contactList
Main Method:
import java.util.Scanner;
import java.io.FileReader;
import java.io.FileNotFoundException;
public class ContactMain {
public static void main(String[] args) {
try {
FileReader filepath = new FileReader("data1.txt");
Scanner k = new Scanner(filepath);
ContactList myList = new ContactList();
while (k.hasNextLine()) {
String i = k.nextLine();
myList.addNode(new ContactNode(i));
}
myList.traverse();
myList.sort();
myList.traverse();
} catch (FileNotFoundException e) {
System.out.println("File Not Found. ");
}
}
}
Node Class:
public class ContactNode {
private String name;
public int index;
private ContactNode prev;
public ContactNode next;
ContactNode(String a) {
name = a;
index = 0;
next = null;
prev = null;
}
public ContactNode getNext() {
return next;
}
public ContactNode getPrev() {
return prev;
}
public String getName() {
return name;
}
public int getIndex() {
return index;
}
public void setNext(ContactNode newnext) {
next = newnext;
}
public void setPrev(ContactNode newprevious) {
prev = newprevious;
}
public void setName(String a) {
name = a;
}
public void setIndex(int b) {
index = b;
}
}
I am making a program for fun that reads in contact information from a text file and puts them into a Linked List. I want to create a sort() method to sort each node or name alphabetically. I've done a good amount of research and my method only prints code like: ContactList#282c0dbe, by as many lines as my text file.
what is ContactList#282c0dbe?
It is class name follow by at sign and hash code at the end, hash code of the object.All classes in Java inherit from the Object class, directly or indirectly . The Object class has some basic methods like clone(), toString(), equals(),.. etc. The default toString() method in Object prints “class name # hash code”.
What is the solution?
You need to override toString method in ContactList class because it is going to give you clear information about the object in readable format that you can understand.
The merit about overriding toString:
Help the programmer for logging and debugging of Java program
Since toString is defined in java.lang.Object and does not give valuable information, so it is
good practice to override it for subclasses.
#override
public String toString(){
// I assume name is the only field in class test
return name + " " + index;
}
For sorting, you should implement Comparator interface since your object does not have natural ordering. In better sense, if you want to define an external controllable ordering behavior, this can override the default ordering behavior
read more about Comparator interface
You need custom Comparator for sorting, and to pretty print your List you need to implement toString() in ContactList class

Class Cast Error trying to use compareTo with node and elements in a linked list

I've looked at a bunch of the questions in this area and can't find one that solves my problem specifically.
Basically, this is a homework assigment where I have a linked list with nodes, which hold an element. The node class (LinearNode) and the element class (Golfer) both implement Comparable and override the compareTo method. However, the runtime fails trying to add a new node to the list (first node is added fine) with a class cast exception: supersenior.LinearNode cannot be cast to supersenior.Golfer. I don't know why it's trying to take the node and compare it to an element of the node to be compared...i've even tried explicitly casting. The following error is observed:
Exception in thread "main" java.lang.ClassCastException: supersenior.LinearNode cannot be cast to supersenior.Golfer
at supersenior.Golfer.compareTo(Golfer.java:12)
at supersenior.LinearNode.compareTo(LinearNode.java:80)
at supersenior.LinearNode.compareTo(LinearNode.java:80)
at supersenior.LinkedList.add(LinkedList.java:254)
at supersenior.SuperSenior.main(SuperSenior.java:100)
Any help would be greatly appreciated. Thanks!
LinkedList class:
package supersenior;
import supersenior.exceptions.*;
import java.util.*;
public class LinkedList<T> implements OrderedListADT<T>, Iterable<T>
{
protected int count;
protected LinearNode<T> head, tail;
/**
* Creates an empty list.
*/
public LinkedList()
{
count = 0;
head = tail = null;
}
public T removeFirst() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException ("List");
LinearNode<T> result = head;
head = head.getNext();
if (head == null)
tail = null;
count--;
return result.getElement();
}
public T removeLast() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException ("List");
LinearNode<T> previous = null;
LinearNode<T> current = head;
while (current.getNext() != null)
{
previous = current;
current = current.getNext();
}
LinearNode<T> result = tail;
tail = previous;
if (tail == null)
head = null;
else
tail.setNext(null);
count--;
return result.getElement();
}
public T remove (T targetElement) throws EmptyCollectionException,
ElementNotFoundException
{
if (isEmpty())
throw new EmptyCollectionException ("List");
boolean found = false;
LinearNode<T> previous = null;
LinearNode<T> current = head;
while (current != null && !found)
if (targetElement.equals (current.getElement()))
found = true;
else
{
previous = current;
current = current.getNext();
}
if (!found)
throw new ElementNotFoundException ("List");
if (size() == 1)
head = tail = null;
else if (current.equals (head))
head = current.getNext();
else if (current.equals (tail))
{
tail = previous;
tail.setNext(null);
}
else
previous.setNext(current.getNext());
count--;
return current.getElement();
}
public boolean contains (T targetElement) throws
EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException ("List");
boolean found = false;
Object result;
LinearNode<T> current = head;
while (current != null && !found)
if (targetElement.equals (current.getElement()))
found = true;
else
current = current.getNext();
return found;
}
public boolean isEmpty()
{
return (count == 0);
}
public int size()
{
return count;
}
public String toString()
{
LinearNode<T> current = head;
String result = "";
while (current != null)
{
result = result + (current.getElement()).toString() + "\n";
current = current.getNext();
}
return result;
}
public Iterator<T> iterator()
{
return new LinkedIterator<T>(head, count);
}
public T first()
{
return head.getElement();
}
public T last()
{
return tail.getElement();
}
#Override
public void add (T element)
{
LinearNode<T>node = new LinearNode<T>();
node.setElement(element);
if(isEmpty())
{
head = node;
if(tail == null)
tail = head;
//node.setNext(head);
//head.setPrevious(node);
//head.setElement((T) node);
count++;
}
else
{
for(LinearNode<T> current = head; current.getNext() != null; current = current.getNext())
if(node.compareTo((T) current) >= 0)
{
current.setPrevious(current);
current.setNext(current);
}
else
{
current.setPrevious(node);
}
tail.setNext(node);
}
}
}
LinearNode class:
package supersenior;
public class LinearNode<E> implements Comparable<E>
{
private LinearNode<E> next, previous;
public E element;
public LinearNode()
{
next = null;
element = null;
}
public LinearNode (E elem)
{
next = null;
element = elem;
}
public LinearNode<E> getNext()
{
return next;
}
public void setNext (LinearNode<E> node)
{
next = node;
}
public E getElement()
{
return element;
}
public void setElement (E elem)
{
element = elem;
}
#Override
public int compareTo(E otherElement) {
return ((Comparable<E>) this.element).compareTo(otherElement);
}
public LinearNode<E> getPrevious()
{
return previous;
}
public void setPrevious (LinearNode<E> node)
{
previous = node;
}
}
The element class (Golfer):
package supersenior;
public class Golfer implements Comparable<Golfer>{
Golfer imaGolfer;
String name;
int tourneys;
int winnings;
double avg;
public Golfer(String attr[]){
this.name = attr[0];
this.tourneys = Integer.parseInt(attr[1]);
this.winnings = Integer.parseInt(attr[2]);
this.avg = findAvg(winnings, tourneys);
}
private double findAvg(int winnings, int tourneys){
double a = winnings/tourneys;
return a;
}
#Override
public String toString(){
return "Name: " + name + " Tourneys: " + tourneys + " Winnings: " + winnings + " Average: " + avg;
}
#Override
public int compareTo(Golfer golfer) {
if(this.avg <= golfer.avg)
return 1;
if(this.avg == golfer.avg)
return 0;
else
return -1;
}
}
The problem is that you're mixing what's being compared. You're trying to compare the LinearNode object (which holds an E) to an actual E. LinearNode<E> shouldn't implement Comparable<E>; if anything, it might implement Comparable<LinearNode<E>>, and the type parameter should probably be E extends Comparable<E>.
If you want to order LinearNodes based on the ordering of their underlying elements, you should use something like this:
// in LinearNode
public int compareTo(LinearNode<E> otherNode) {
return this.element.compareTo(otherNode.element);
}
(Note that the Java sorted collections don't require elements to implement Comparable, since you can provide a custom Comparator for any of them, but in the case of this assignment it's probably fine to require that E extends Comparable<E>.)
(Note 2: If you're using Generics, any cast, such as your (Comparable<E>), is a red flag; the purpose of the Generics system is to eliminate the need for most explicit casts.)

Java: Generic Class Exception

I was designing a generic linked list to create a linked list of Strings.
However I keep getting this error :
Exception in thread "main" java.lang.NoSuchMethodError: Node.<init>(Ljava/lang/Object;)V
at LinkedList.addNode(LinkedList.java:10)
at LinkedList.<init>(LinkedList.java:22)
at Trial.main(Trial.java:7)
From the stack trace , the error is generated at LinkedList's addNode() method. Im including the definition to this method as well as the definition of the Node class.
LinkedList addNode()
public void addNode(T n) {
Node<T> temp = new Node<T>(n);
if(start==null) {
start = temp;
current = start;
} else {
end.setNext(temp);
}
end =temp;
}
Node.java
public class Node<T>{
private T n;
Node next;
Node(T n) {
this.n = n;
next = null;
}
public void setNext(Node nextNode) {
next = nextNode;
}
public Node getNext() {
return next;
}
public T getN() {
return n;
}
#Override
public String toString() {
if(n instanceof String)
return n.toString();
else {
return T.toString();
}
}
}
LinkedList.java
public class LinkedList<T>{
Node start;
Node end;
Node current;
private static final long serialVersionUID = 901L;
LinkedList(T n) {
addNode(n);
}
public void addNode(T n) {
Node<T> temp = new Node<>(n);
if(start==null) {
start = temp;
current = start;
} else {
end.setNext(temp);
}
end =temp;
}
LinkedList(T[] n) {
for(T print : n)
addNode(print);
}
public void addNode(T[] n) {
if(n!=null) {
for (T values : n) {
addNode(values);
}
}
}
public void incC() {
current = current.getNext();
}
public void insert(T n) {
Node newNode = new Node(n);
if(current==start){
newNode.setNext(current);
start = newNode;
}else {
Node tempstart = start;
Node prevAdd=null;
while(tempstart!=current){
prevAdd = tempstart;
tempstart = tempstart.getNext();
}
prevAdd.setNext(newNode);
newNode.setNext(current);
}
}
public void find(T x) {
Node tempstart;
tempstart = start;
while (tempstart!=null) {
if(tempstart.getN()==x) {
System.out.println("Element found");
tempstart = tempstart.getNext();
} else {
tempstart = tempstart.getNext();
}
}
}
public void delete(T x) {
Node previous=null;
Node tempstart = start;
while(tempstart!=null) {
if(tempstart.getN()==x) {
if(previous ==null) {
previous = tempstart;
tempstart = tempstart.getNext();
start = tempstart;
previous.setNext(null);
previous = null;
} else {
tempstart = tempstart.getNext();
previous.setNext(tempstart);
}
}else {
previous = tempstart;
tempstart = tempstart.getNext();
}
}
}
#Override
public String toString() {
Node tempNode = start;
String str = "Values: ";
while (tempNode!=null) {
str = str + " " + tempNode.toString();
tempNode = tempNode.getNext();
}
return str;
}
}
Trial.java
public class Trial {
public static void main(String[] args) {
String[] para = {"Hollo","this","is","me"};
LinkedList<String> L1;
L1 = new LinkedList<String>(para);
System.out.println(L1);
}
return T.toString();
this doesn't work. T is a type variable and only available at compile time due to type erasure.
But apart from that, I can't see what's wrong, you need to poost more code from your LinkedList class.
You should declare the start, end, and current fields in LinkedList< T > and the next field in Node< T > as type Node< T >, not Node. Don't use raw types anywhere in the code, because they translate into Node< Object >.
Your class Nodedoes not compile, so it is likely that you should first fix that issue before continuing:
return T.toString();
does not make sense. Probably that just writing this:
return n.toString();
is enough for now.
In Node.java, in the method
#Override
public String toString() {
if(n instanceof String)
return n.toString();
else {
return T.toString();
}
}
// the below statement thows compilation error.
return T.toString();
Your Node Constructor is not public, so it will not work if you call it from a class in another package.

Categories

Resources