I have two classes.
One is a Phrase class,
import java.util.List;
import java.util.ArrayList;
#SuppressWarnings("unchecked")
public class Phrase
{
List<String> papers = new ArrayList();
String name = "";
boolean multiple = false;
public Phrase(String name, List list)
{
this.name = name;
this.papers = list;
if(list.size() > 1)
{
multiple = true;
}
}
public Phrase(String name, String pName)
{
this.name = name;
this.papers.add(pName);
multiple = false;
}
public void addPaper(String paper)
{
papers.add(paper);
multiple = true;
}
public String getPhrase()
{
return name;
}
public List<String> getPapers()
{
return papers;
}
}
The Other is a KeyedLinkedList.
public class KeyedLinkedList<K,Phrase>
{
private KeyNode first;
private int size;
private class KeyNode
{
K key;
Phrase value;
KeyNode previous;
KeyNode next;
public KeyNode(K key, Phrase value, KeyNode previous, KeyNode next)
{
this.key = key;
this.value = value;
this.previous = previous;
this.next = next;
}
}
public int size()
{
return size;
}
public boolean put(K key, Phrase val)
{
if(isEmpty())
{
first = new KeyNode(key, val, null, null);
first.next = first;
first.previous = first;
size++;
return true;
}
KeyNode temp = first;
if(temp.key.equals(key))
{
//****ERROR LOCATION****//
temp.value.addPaper(val.getPapers().get(0));
//****ERROR LOCATION****//
if(temp.value.getPapers().size() < 3)
return false;
return true;
}
temp = temp.next;
while(temp != first)
{
if(temp.key.equals(key))
{
temp.value.addPaper(val.getPapers().get(0));
if(temp.value.getPapers().size() < 3)
return false;
return true;
}
temp = temp.next;
}
temp.previous.next = new KeyNode(key, val, temp.previous.next, first);
first.previous = temp.previous.next;
size++;
return true;
}
}
When I compile this I get the error: "Can't find symbol - method getPapers()"
I obviously have the getPapers() method in my Phrase class and val in the parameters is a Phrase object. I am wondering what I need to do to fix this problem. The error occurs half way through the put method.
public class KeyedLinkedList<K,Phrase>
// ^^^^^^
Here, you're declaring a type variable which has the same name as the Phrase class and shadows it. Any variables declared with the type Phrase refer to this type variable instead of the Phrase class.
Since I have no idea what your intent was, I can't really advise anything except to remove that.
public class KeyedLinkedList<K>
BTW, don't do this:
List<String> papers = new ArrayList();
// ^^^^^^^^^
It's called a raw type, it's bad, and there's no reason to use it. Do new ArrayList<String> instead.
Related
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.
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 created my own linked list, but when I tried to run it there is an error:
Exception in thread "main" java.lang.NullPointerException
at List.add(List.java:8) //if(t.val ==null)
at main.main(main.java:38) //linput.add(inputLine.split(" ")[i]);
Here is my List class:
class List{
String val;
List next=null;
private List t;
public void add(String word){
if(t.val ==null)
t.val=word;
else while(!t.next.val.equals(null))
{
t=t.next;
if(t.next.val.equals(null))
{
t.next.val=word;
break;
}
}
}
public int get(String word)
{
int i=0;
if(t.val.equals(word))
i=0;
else while(!t.next.val.equals(word))
{
t=t.next;
i++;
if(t.next.val.equals(word))
{
i++;
}
}
return i;
}
public String indexOf(int i)
{
int counter=0;
while(counter<i)
{
t=t.next;
counter++;
}
return t.val;
}
}
And here is my main function :
static public void main(String[] args)
{
List linput = new List();
String inputLine = "Hey look at me.";
for(int i = 0 ; i < inputLine.split(" ").length ; i++)
{
linput.add(inputLine.split(" ")[i]);
}
System.out.println(linput.indexOf(0)+" "+linput.indexOf(1)+" "+linput.indexOf(2));
}
I initialized t but next time there is an error like this:
private List t =new List();
Exception in thread "main" java.lang.StackOverflowError
at List.<init>(List.java:5)
at List.<init>(List.java:5)
at List.<init>(List.java:5)
Sorry. I can't give my full code, because the rest of my code is working well (reading from txt etc....).
The error seems to be related to the variable 't' (i.e., private List t).
Did you initialize this variable ? The if (t.val == null) seems to be cribbing this as t is null (uninitialized) at this point
You should have allocated object (using new) for this variable.
Can you share the full code for the constructor of List ?
Assuming you want to implement a simple forward list, rather than use the Java LinkedList class, you need to:
Change your implementation of the list to reference nodes in the list
handle traversal of the linked nodes in your word list
Here is an example:
WordList class
package com.example.words;
class WordList {
private WordNode head = null;
private int listSize = 0;
public void add(String word) {
// TODO add check for duplicate word
if (head == null) {
head = new WordNode();
head.setValue(word);
listSize++;
} else {
WordNode current = head;
while (current.getNext() != null) {
current = current.getNext();
}
WordNode newNode = new WordNode();
newNode.setValue(word);
current.setNext(newNode);
listSize++;
}
}
public int getWordIndex(String word) {
WordNode current = head;
int index = 0;
boolean found = false;
while (!found && current != null) {
found = current.getValue().equalsIgnoreCase(word);
if (!found) {
index++;
current = current.getNext();
}
}
if (found) {
return index;
} else {
return -1;
}
}
public String indexOf(int i) {
int index = 0;
WordNode current = head;
if (i <= listSize) {
while (index < i) {
current = current.getNext();
index++;
}
return current.getValue();
} else {
return null;
}
}
public int size() {
return listSize;
}
}
WordNode Class
package com.example.words;
public class WordNode {
private String value;
private WordNode next = null;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public WordNode getNext() {
return next;
}
public void setNext(WordNode link) {
next = link;
}
}
Test Driver
package com.example.words;
public class Test {
public static void main(String[] args) {
//TODO handle punctuation
WordList myList = new WordList();
String inputLine = "Hey look at me.";
String[] pieces = inputLine.split(" ");
for (int i=0; i < pieces.length; i++) {
myList.add(pieces[i]);
}
for (int i=0; i < pieces.length; i++) {
String value = myList.indexOf(i);
if (value.equalsIgnoreCase(pieces[i])) {
System.out.println("Following node is wrong:");
}
System.out.println ("node " + i + ". = " + value);
}
}
}
You tried to create t as a member variable of its own class like this:
class List {
[...]
private List t = new List();
[...]
}
This won't work because the constructor of List would be called indefinitely.
Try lazy instantiation of t instead. Replace all access of t with a getter:
private List getT() {
if (this.t == null) {
this.t = new List();
}
return t;
}
I would like to create a third list by connecting 2 others. I tried to do it, but as I expected my idea was wrong and everything doesn't work fine. Below you can see List file and test program. The other (empty) constructors of List are meant to connect 2 lists by adding elements of one List before specific index of the second list, and adding elements of one List before specific element of the second one using equals() method. It will be also hard for me for sure, but I ask only for simply connecting elements to obtain something like that:
(L11, L12, L13)+(L21, L22, L23) = L11,L12,L13,L21,L22,L23
public class Lista implements List {
private Element head = new Element(null); //wartownik
private int size;
public Lista(){
clear();
}
public Lista(Lista lista1, Lista lista2) {
head.previous = lista2.head.previous;
head.next = lista1.head.next;
}
public Lista(Lista lista1, Lista lista2, int index) {
}
public Lista(Lista lista1, Lista2. Object value) {
}
public void clear(){
head.setPrevious(head);
head.setNext(head);
size=0;
}
public void insert(int index, Object value) throws IndexOutOfBoundsException {
if (index<0 || index>size) throw new IndexOutOfBoundsException();
Element element = new Element(value);
element.wstawPrzed(getElement(index));
++size;
}
public Element getElement(int index) {
Element szukany = head.getNext();
for (int i=index; i>0; --i)
szukany = szukany.getNext();
return szukany;
}
public Object get(int index) throws IndexOutOfBoundsException{
if(index<0 || index>size) throw new IndexOutOfBoundsException();
Element particular = head.getNext();
for(int i=0; i <= index; i++)
particular = particular.getNext();
return particular.getValue();
}
public boolean delete(Object o){
if(head.getNext() == null) return false;
if(head.getNext().getValue().equals(o)){
head.setNext(head.getNext().getNext());
size--;
return true;
}
Element delete = head.getNext();
while(delete != null && delete.getNext() != null){
if(delete.getNext().getValue().equals(o)){
delete.setNext(delete.getNext().getNext());
size--;
return true;
}
delete = delete.getNext();
}
return false;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
public void infoOStanie() {
if (isEmpty()) {
System.out.println("Lista pusta.");
}
else
{
System.out.println("Lista zawiera " + size() + " elementow.");
}
}
public IteratorListowy iterator() {
return new IteratorListowy();
}
public void wyswietlListe() {
System.out.println();
IteratorListowy iterator = iterator();
for (iterator.first(); !iterator.isDone(); iterator.next())
{
System.out.println(iterator.current());
}
System.out.println();
}
private static final class Element{
private Object value;
private Element next; //Referencja do kolejnego obiektu
private Element previous; //Referencja do elementu poprzedniego
public Element(Object value){
setValue(value);
}
public void setValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
//ustawia referencję this.next na obiekt next podany w atgumencie
public void setNext(Element next) {
if (next != null)
this.next = next;
}
public Element getNext(){
return next;
}
public void setPrevious(Element previous) {
if (previous != null)
this.previous = previous;
}
public Element getPrevious() {
return previous;
}
public void wstawPrzed(Element next) {
Element previous = next.getPrevious();
setNext(next);
setPrevious(previous);
next.setPrevious(this);
previous.setNext(this);
}
public void delete() {
previous.setNext(next);
next.setPrevious(previous);
}
}
private class IteratorListowy implements Iterator{
private Element current;
public IteratorListowy() {
current = head;
}
public void next() {
current = current.next;
}
public void previous() {
current = current.previous;
}
public boolean isDone() {
return current == head;
}
public Object current() {
return current.value;
}
public void first() {
current = head.getNext();
}
public void last() {
current = head.getPrevious();
}
}
}
test
public class Program {
public static void main(String[] args) {
Lista lista1 = new Lista();
Lista lista2 = new Lista();
Lista lista3 = new Lista(lista1, lista2);
Student s1 = new Student("Kowalski", 3523);
Student s2 = new Student("Polański", 45612);
Student s3 = new Student("Karzeł", 8795);
Student s4 = new Student("Pałka", 3218);
Student s5 = new Student("Konowałek", 8432);
Student s6 = new Student("Kłopotek", 6743);
Student s7 = new Student("Całka", 14124);
Student s8 = new Student("Pabin", 1258);
Student s9 = new Student("Dryjas", 7896);
Student s10 = new Student("Zając", 5642);
lista1.insert(0, s1);
lista1.insert(0, s2);
lista1.insert(0, s3);
lista1.insert(0, s4);
lista1.insert(0, s5);
lista1.wyswietlListe();
lista1.infoOStanie();
lista2.insert(0, s6);
lista2.insert(0, s7);
lista2.insert(0, s8);
lista2.insert(0, s9);
lista2.insert(0, s10);
lista2.wyswietlListe();
lista2.infoOStanie();
lista3.wyswietlListe();
}
}
As I understood you are trying to concatenate two doubly linked lists list1 and list2, so you would need this simple logic :
// tail of list1 should point to head of list2
lista1.tail.next = lista2.head;
// as we are doubly linked, head of list2 should point back to tail of list1
lista2.head.previous = lista1.tail
this is it, the head of the list1 will now be the head of result list.
Now, doing it in your constructor :
public Lista(Lista lista1, Lista lista2) {
// get hold of lisa1.tail
Element lista1Tail = lista1.getElement(lista1.size() - 1);
listaTail.next = lista2.head;
//now pointer back to tail of lista1
lista2.head.previous = listaTail;
}
This will work, given you fix your getElement() method (which now return not correct index) and add null pointer checks for boundary cases.
As a simpler alternative, I recommend keeping tail member of your list, it is cleaner and more performant.
I have LinkedList with test program. As you can see in that program I add some Students to the list. I can delete them. If I choose s1,s2,s3 oraz s4 to delete everything runs well, and my list is printed properly and information about number of elements is proper. But if I delete last element (in this situation - s5) info about number of elements is still correct, but this element is still printed. Why is that so? Where is my mistake?
public class Lista implements List {
private Element head = new Element(null); //wartownik
private int size;
public Lista(){
clear();
}
public void clear(){
head.setNext(null);
size=0;
}
public void add(Object value){
if (head.getNext()==null) head.setNext(new Element(value));
else {
Element last = head.getNext();
//wyszukiwanie ostatniego elementu
while(last.getNext() != null)
last=last.getNext();
// i ustawianie jego referencji next na nowowstawiany Element
last.setNext(new Element(value));}
++size;
}
public Object get(int index) throws IndexOutOfBoundsException{
if(index<0 || index>size) throw new IndexOutOfBoundsException();
Element particular = head.getNext();
for(int i=0; i <= index; i++)
particular = particular.getNext();
return particular.getValue();
}
public boolean delete(Object o){
if(head.getNext() == null) return false;
if(head.getNext().getValue().equals(o)){
head.setNext(head.getNext().getNext());
size--;
return true;
}
Element delete = head.getNext();
while(delete != null && delete.getNext() != null){
if(delete.getNext().getValue().equals(o)){
delete.setNext(delete.getNext().getNext());
size--;
return true;
}
delete = delete.getNext();
}
return false;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
public IteratorListowy iterator() {
return new IteratorListowy();
}
public void wyswietlListe() {
IteratorListowy iterator = iterator();
for (iterator.first(); !iterator.isDone(); iterator.next())
{
System.out.println(iterator.current());
}
System.out.println();
}
public void infoOStanie() {
if (isEmpty()) {
System.out.println("Lista pusta.");
}
else
{
System.out.println("Lista zawiera " + size() + " elementow.");
}
}
private static final class Element{
private Object value;
private Element next; //Referencja do kolejnego obiektu
public Element(Object value){
setValue(value);
}
public void setValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
//ustawia referencję this.next na obiekt next podany w atgumencie
public void setNext(Element next) {
if (next != null)
this.next = next;
}
public Element getNext(){
return next;
}
}
private class IteratorListowy implements Iterator{
private Element current;
public IteratorListowy() {
current = head;
}
public void next() {
current = current.next;
}
public boolean isDone() {
return current == null;
}
public Object current() {
return current.value;
}
public void first() {
current = head.getNext();
}
}
}
test
public class Program {
public static void main(String[] args) {
Lista lista = new Lista();
Iterator iterator = lista.iterator();
Student s1 = new Student("Kowalski", 3523);
Student s2 = new Student("Polański", 45612);
Student s3 = new Student("Karzeł", 8795);
Student s4 = new Student("Pałka", 3218);
Student s5 = new Student("Konowałek", 8432);
Student s6 = new Student("Kłopotek", 6743);
Student s7 = new Student("Ciołek", 14124);
lista.add(s1);
lista.add(s2);
lista.add(s3);
lista.add(s4);
lista.add(s5);
lista.wyswietlListe();
lista.delete(s5);
lista.wyswietlListe();
lista.infoOStanie();
lista.clear();
lista.infoOStanie();
}
}
The problem is that your setNext(Element next) method does not set anything if next == null. And that is the case for the last element of your list.
So when you call delete.setNext(delete.getNext().getNext());, nothing is actually set because delete.getNext().getNext() is null!
Remove the if (next != null) condition in setNext and it will work.