Generics collection implementation java compilation error - java

EDIT :
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
public synchronized E get() {
if (current!=null) return current.data;
return null;
}
}
}
the problem is that i get the following compilation Error on the emphasized lines :
> Type mismatch: cannot convert from LinkedList<E>.Node<E> to
> LinkedList<E>.Node<E>
what does it mean? and how do i fix this?
btw, the code is only part of the implementation so dont try to logicly figure it out.

--- Edited as the question changes slightly ---
The question is now becoming, how do I have two inner classes coordinate generic types? In short, they don't have to if they are both inner classes of an outer class where the generic type is bound. So even with the public synchronized E get() in the non-generic LinkedListIterator you are returning an E (and it is type safe).
However, if you then reach out to implement java.util.Iterator<E> things fall apart, because that E is based on a different class (interface) so the E has different scoping. How do you fix this? You need to parameterize your Node classes to Node<E> to satisfy that E bindings exist on the implementation of Iterator even when that implementation is being used outside of the scope of it's originating class. This forces Node<E> to be defined statically.
The reason it forces the static definition of Node<E> has to do with garbage collection. An Iterator might still be holding references to Nodes even though the LinkedList is scheduled for garbage collection. Sure, you might be able to keep such a thing from happening with a specific implementation, but the JVM has to allow any implementation (even an errant one).
Perhaps it is easier to explain with code
public LinkedList<E> {
public Iterator<E> iterator() {
return new LinkedIterator(head);
}
// private because we don't want instances created outside of this LinkedList
private class LinkedIterator implements Iterator<E> {
// Right here, needing a parameterized next node will force Node to be static
// static inner classes can exist outside of the scope of their parent
// Since it can exist outside of the parent's scope, it needs it's own generic parameter
private Node<E> next;
LinkedIterator(Node start) {
next = start;
}
public boolean hasNext() {
return next != null;
}
public E next() {
Node<E> retValue = next;
if (retValue != null) {
next = retValue.next;
}
return retValue;
}
}
// must be static because LinkedList might be garbage collected when
// an Iterator still holds the node.
// This E is not the same E as in LinkedList, because it is a E declaration (hiding the above E)
private static Node<E> {
Node<E> next;
Node<E> prev;
E data;
}
}
If you are not careful, you can now wind up back where you started; however, the key is to construct new Node<E> objects when needed in the parent scope. Since that is the same scope where you construct LinkedIterator types, the generic type safety will be ensured.
--- Original post follows ----
By specifying that your node class definition is a Node<E>, you basically create a second, independently scoped generic type E which will hide the outer generic type E in the LinkedList class.
Since none of your classes are static, they will only exist within context of a LinkedList class, which will provide the generics binding. That means you can simplify Node<E> to Node yet still put E class types within the Node class. Same goes for the LinkedListIterator, except that if you want it to implement Iterator you should indicate it implements Iterator<E>.
Due to request, what follows is the code that compiles on my machine, (java 1.6.0_20)
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}

You overdid it a bit by parametrising the embedded classes. I removed all unnecessary ones.
public class LinkedList<E> {
private class Node {
protected Node next, prev;
protected E data;
protected Node(E dat) {
data = dat;
next = prev = null;
}
}
private Node head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}
Alternatively with a static class Node.
public class LinkedList<E> {
private static class Node<E2> {
protected Node next, prev;
protected E2 data;
protected Node(E2 dat) {
data = dat;
next = prev = null;
}
}
private Node<E> head, tail;
public LinkedList() {
(head = new Node(null)).next = tail = new Node(null);
tail.prev = head;
tail.next = head.prev = null;
}
public class LinkedListIterator {
private Node<E> current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}
}

It doesn't understand that the <E> in LinkedListIterator is the same <E> as the parent class. Just remove from the inner class:
public class LinkedListIterator {
private Node<E> current = null;
public synchronized void resetToHead() {
current = head.next;
}
public synchronized void resetToTail() {
current = tail.prev;
}
}

Related

Why using a class as a variable member inside that said class

I am new to Java and been studying it. So I am having trouble to understand what are these and how it being processed by Java also why are we declaring these variables like that. I mean can you educate me on this?
Public abstract class ListItem {
protected Listitem leftLink = null;
protected Listitem rightLink = null;
protected Object value;
some code here
}
Thanks in advance!
Why declare a Class field which has the ClassName as variable type instead of a int, string... ?
Because the developer needs to. Sometimes, an instance of a class must reference another instance of the same class. A typical example is the LinkedList.
Consider a linked list as a sequence of nodes. Each node knows the next one to be linked. Here would be a naive implementation of a node:
class Node<T> {
private Node<T> next;
private T value;
Node(T value) {
this.value = value;
}
public T getValue() {
return value;
}
void setNext(Node<T> next) {
this.next = next;
}
}
As you can see, the class Node contains a variable member of type Node, to reference the next element of the linked list. Finally, a simplistic implementation of the linked list would be:
class LinkedList<T> {
private Node<T> first;
private Node<T> last;
private int length = 0;
public void add(T value) {
Node<T> node = new Node<T>(value);
if(length != 0) {
last.setNext(node);
last = node;
}
else {
first = node;
last = node;
}
length++;
}
public Node<T> getFirst() {
return first;
}
}
When a new node is added to the collection, the previous last node references it and therefore, becomes the new last node.

Need guidance on creating Node class (java)?

I need to implement a Node class, where the basic methods are: getItem(), getNext(), setItem() and setNext(). I want the nodes to be able to store at least the default integer range in Java as the “item”; the “next” should be a reference or pointer to the next Node in a linked list, or the special Node NIL if this is the last node in the list.I also want to implement a two-argument constructor which initializes instances with the given item (first argument) and next node (second argument) , I've kind of hit a brick wall and need some guidance about implementing this , any ideas ?
I have this so far:
class Node {
public Node(Object o, Node n) {
}
public static final Node NIL = new Node(Node.NIL, Node.NIL);
public Object getItem() {
return null;
}
public Node getNext() {
return null;
}
public void setItem(Object o) {
}
public void setNext(Node n) {
}
}
While implementing the custom LinkedList/Tree, we need Node. Here is demo of creating Node and LinkedList. I have not put in all the logic. Just basic skeleton is here and you can then add more on yourself.
I can give you a quick hint on how to do that:
Class Node{
//these are private class attributes, you need getter and setter to alter them.
private int item;
private Node nextNode;
//this is a constructor with a parameter
public Node(int item)
{
this.item = item;
this.nextNode = null;
}
// a setter for your item
public void setItem(int newItem)
{
this.item = newItem;
}
// this is a getter for your item
public int getItem()
{
return this.item;
}
}
You can create a Node object by calling:
Node newNode = Node(2);
This is not a complete solution for your problem, the two parameter constructor and the last node link are missing, but this should lead you in the correct direction.
Below is a simple example of the Node implementation, (i renamed Item to Value for readability purpose). It has to be implemented somehow like this, because methods signatures seems to be imposed to you. But keep in mind that this is definely not the best way to implement a LinkedList.
public class Node {
public static final Node NIL = null;
private Integer value;
private Integer next;
public Node(Integer value, Node next) {
this.value = value;
this.next = next;
}
public Integer getValue() {
return this.value;
}
public Node getNext() {
return this.next;
}
public void setValue(Integer value) {
this.value = value;
}
public void setNext(Node next) {
this.next = next;
}
public boolean isLastNode() {
return this.next == Node.NIL || Node;
}
}
public class App {
public static void main(String[] args) {
Node lastNode = new Node(92, Node.NIL);
Node secondNode = new Node(64, lastNode);
Node firstNode = new Node(42, secondNode);
Node iterator = firstNode;
do () {
System.out.println("node value : " + iterator.getValue());
iterator = iterator.getNext();
} while (iterator == null || !iterator.isLastNode());
}
}
The node class that will be implemented changes according to the linked list you want to implement. If the linked list you are going to implement is circular, then you could just do the following:
public class Node {
int data;
Node next = null;
public Node(int data){
this.data = data;
}
}
Then how are you going to implement the next node?
You are going to do it in the add method of the circularLinkedList class. You can do it as follows:
import java.util.*;
public class CircularLinkedList {
public CircularLinkedList() {}
public Node head = null;
public Node tail = null;
public void add(int data) {
Node newNode = new Node(data);
if(head == null) {
head = newNode;
}
else {
tail.next = newNode;
}
tail = newNode;
tail.next = head;
}
public void displayList() {
System.out.println("Nodes of the circular linked list: ");
Node current = head;
if(head == null) {
System.out.println("Empty list...");
}
else {
do {
System.out.print(" " + current.data);
current = current.next;
}while(current != head);
System.out.println();
}
}
}

Java - Custom iterator not able to track head of custom linked list

The classes are not complete, but here's what I have so far and I expected the test below to pass.
public class LinkedList<T> extends AbstractSequentialList<T> {
private Node<T> head;
#Override
public boolean add(T element) {
if(head == null) {
head = new Node(element);
}
return true;
}
#Override
public ListIterator<T> listIterator(int index) {
return new LinkedListIterator<>();
}
#Override
public int size() {
return 0;
}
private class LinkedListIterator<T> implements ListIterator<T> {
private Node<T> current;
public LinkedListIterator() {
current = (Node<T>) head;
}
#Override
public boolean hasNext() {
return (current != null && current.getNext() != null)? true : false;
}
#Override
public T next() {
return null;
}
}
}
Here is the Node class.
public class Node<T> {
private T value;
private Node next;
public Node(T value) {
this.value = value;
}
public Node(T value, Node next) {
this.value = value;
this.next = next;
}
public T getValue() {
return value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
My iterator test is like this.
LinkedList<String> list;
ListIterator<String> iterator;
#Before
public void setUp() throws Exception {
list = new LinkedList<>();
iterator = list.listIterator();
}
#Test
public void testHasNext() throws Exception {
assertThat(iterator.hasNext(), is(false));
list.add("Hello World");
assertThat(iterator.hasNext(), is(true));
}
However, I'm failing on the second assertion. My issue is that the "current" pointer in the iterator is always null even though I'm setting it to the head of the enclosing LinkedList class. How can I fix this? Thanks.
It looks the value of current is set inside the constructor of LinkedListIterator.
It hasn't been updated after you have added an element to the list. This seems to your problem here.
What is wrong is your test, IMO.
You shouldn't expect the iterator to point to the first element if the first element has been added after the iterator has been constructed.
Now, why does your iterator work this way? Because Java is pass-by-value. When you construct an iterator, the iterator receives a copy of the reference to the first node of the list. And at this time, this reference is null, because you haven't added any node yet.
If you really want the iterator to "see" the first node of the list even after it has been constructed, then the iterator needs to get the first node of the list in hasNext(), not in the constructor.

Iterator for a linkedlist

My project should implement two classes. A basic linked list and a sorted linked list. Everything seems to be working fine except for some reason I can't iterate through the sorted linked list. The class structure is as follows:
public class BasicLinkedList<T> implements Iterable<T> {
public int size;
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
public BasicLinkedList() {
head = tail = null;
}
//Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if(hasNext()){
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove(){
throw new UnsupportedOperationException("Remove not implemented.");
}
};
Now when I test this class it works just fine. The iterator works and I can test it all. The problem is in the sorted linked list class which extends this one. Here's its implementation and a comparator class that I'm using in the constructor:
public class SortedLinkedList<T> extends BasicLinkedList<T>{
private class Node{
private T data;
private Node next;
private Node(T data){
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator){
super();
this.comp = comparator;
}
Here's the comparator class and the test I ran in a separate class:
public class intComparator implements Comparator<Integer>{
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for(int i: sortedList){
System.out.println(i);
}
}
Nothing prints out. I assumed the iterator that was inherited would help me traverse this no problem and clearly its legal because the for-each loop compiles. It's just that nothing gets printed out. I debugged it and all the adding, removing stuff works as expected. It's just that the iterator isn't doing what it's supposed to. Should I create a separate new iterator for this class? But wouldn't that be redundant code since I already inherit it? Help appreciated!
EDIT: Here's the add method for the sorted list
public SortedLinkedList<T> add(T element){
Node n = new Node(element);
Node prev = null, curr = head;
if(head == null){
head = n;
tail = n;
}
//See if the element goes at the very front
else if(comp.compare(n.data, curr.data) <= 0){
n.next = head;
head = n;
}
//See if the element is to be inserted at the very end
else if(comp.compare(n.data, tail.data)>=0){
tail.next = n;
tail = n;
}
//If element is to be inserted in the middle
else{
while(comp.compare(n.data, curr.data) > 0){
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
1) SortedLinkedList extends BasicLinkedList but both have
private Node head;
private Node tail
this is wrong. If you want to inherit those field in the sub class, you should mark the variables as protected in the super class and remove them from the subclass.
2) Same goes for private class Node. You are declaring the Node class in both the SortedLinkedList and BasicLinkedList. What you should do is declare it once, (maybe in the super class?) and use the same class in both places. If you do this, the constructor, and the fields should be accessible to both classes. So you will have to change the access modifier (private is what you have now).
I will post below code that works, but I haven't spent any time on the design. Just posting it to demonstrate how you could change the code to make it work. You will have to decide which access modifiers to use and where to put the classes.
import java.util.Comparator;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for (int i : sortedList) {
System.out.println(i);
}
}
}
class BasicLinkedList<T> implements Iterable<T> {
public int size;
class Node {
T data;
Node next;
Node(T data) {
this.data = data;
next = null;
}
}
protected Node head;
protected Node tail;
public BasicLinkedList() {
head = tail = null;
}
// Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if (hasNext()) {
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove not implemented.");
}
};
}
}
class SortedLinkedList<T> extends BasicLinkedList<T> {
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator) {
super();
this.comp = comparator;
}
public SortedLinkedList<T> add(T element) {
Node n = new Node(element);
Node prev = null, curr = head;
if (head == null) {
head = n;
tail = n;
}
// See if the element goes at the very front
else if (comp.compare(n.data, curr.data) <= 0) {
n.next = head;
head = n;
}
// See if the element is to be inserted at the very end
else if (comp.compare(n.data, tail.data) >= 0) {
tail.next = n;
tail = n;
}
// If element is to be inserted in the middle
else {
while (comp.compare(n.data, curr.data) > 0) {
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
}
class intComparator implements Comparator<Integer> {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}

MergeSorting LinkedList in Java recursively

So the task is to implement a linked-list and merge-sort which sorts linked-lists. I am fully aware that in industry I most likely won't have to implement any of these but I feel it's a good way to practice Java. Here is what I've got up to this point:
Node class:
public class Node<E extends Comparable<E>>
{
public E data;
public Node<E> next;
public Node(E data)
{
this.data = data;
next = null;
}
public void printData()
{
System.out.print(data + " ");
}
}
LinkedList class:
public class LinkedList<E extends Comparable<E>>
{
protected Node<E> root;
protected int size = 0;
public LinkedList()
{
root = null;
}
public void addBeg(E e)
{
Node<E> newNode = new Node<E>(e);
newNode.next = root;
root = newNode;
size++;
}
public Node deleteBeg()
{
Node<E> temp = root;
if(!isEmpty())
{
root = root.next;
size--;
}
return temp;
}
public void setRoot(Node<E> newRoot)
{
root = newRoot;
}
public boolean isEmpty()
{
return root == null;
}
public Node<E> getRoot()
{
return root;
}
public void printList()
{
Node<E> cur = root;
while(cur!=null)
{
cur.printData();
cur=cur.next;
}
System.out.println();
}
}
MergeSorter Class:
public class MergeSorter<E extends Comparable<E>>
{
public MergeSorter()
{
}
private void split(LinkedList<E> list, LinkedList<E> firHalf, LinkedList<E> secHalf)
{
//if 0 or only 1 elements in the list - it doesn't seem to work, however
if(list.getRoot() == null || list.getRoot().next == null)firHalf = list;
else{
Node<E> slow = list.getRoot();
Node<E> fast = list.getRoot().next;
while(fast!=null)
{
fast = fast.next;
if(fast!=null)
{
fast = fast.next;
slow = slow.next;
}
}
//If I use the following line firHalf list is empty when in the caller of this method (it's not in this method, however). Don't understand why ):
//firHalf = list;
firHalf.setRoot(list.getRoot());
secHalf.setRoot(slow.next);
slow.next = null;
}
}
private LinkedList<E> merge(LinkedList<E> a, LinkedList<E> b)
{
LinkedList<E> mergedList = new LinkedList<E>();
Node<E> dummy = new Node<E>(null);
Node<E> tail = dummy;
while(true)
{
if(a.getRoot() == null){
tail.next = b.getRoot();
break;
}
else if(b.getRoot() == null){
tail.next = a.getRoot();
break;
}
else
{
if(a.getRoot().data.compareTo(b.getRoot().data) <= 0)
{
tail.next = a.getRoot();
tail = tail.next;
a.setRoot(a.getRoot().next);
}
else
{
tail.next = b.getRoot();
tail = tail.next;
b.setRoot(b.getRoot().next);
}
tail.next = null;
}
}
mergedList.setRoot(dummy.next);
return mergedList;
}
public void mergeSort(LinkedList<E> list)
{
Node<E> root = list.getRoot();
LinkedList<E> left = new LinkedList<E>();
LinkedList<E> right = new LinkedList<E>();
if(root == null || root.next == null) return; //base case
split(list, left, right); //split
mergeSort(left);
mergeSort(right);
list = merge(left, right); // when this mergeSort returns this list should be
// referenced by the left or right variable of the
// current mergeSort call (but it isn't!)
}
}
I am fairly new to Java (coming from a C background) so I am sincerely sorry in advance if my code is utterly false. When I test the split and merge methods in the MergeSorter class independently, everything seems to work (splitting a list consisting of 0 or 1 element is not working and is driving me crazy but this is not needed for merge-sorting). The mergeSort method, however, is not working and I can't seem to figure out way. I tried to debug it myself and there's seems to be a problem when two halves are merged into one list and then the recursion returns. The newly merged list should be referenced by either the left or right variable of the current mergeSort call but instead I get only the last element instead of the whole list.
Method arguments in Java are always passed by value.
This can be a bit confusing, since objects are always accessed via references, so you might think they're passed by reference; but they're not. Rather, the references are passed by value.
What this means is, a method like this:
public void methodThatDoesNothing(Object dst, Object src) {
src = dst;
}
actually does nothing. It modifies its local variable src to refer to the same object as the local variable dst, but those are just local variables that disappear when the function returns. They're completely separate from whatever variables or expressions were passed into the method.
So, in your code, this:
firHalf = list;
does not really do anything. I guess what you want is:
while (! firHalf.isEmpty()) {
firHalf.deleteBeg();
}
if (! list.isEmpty()) {
firHalf.addBeg(list.root().data);
}
which modifies the objected referred to by firHalf so it has the same zero-or-one elements as list.

Categories