I am creating a implementation of a LinkedList using just a few of the methods in the standard implementation. I have faced a problem when adding the Iterator functionality to my LinkedList.
Right now I can add some elements, and then to something like this
class testList {
public static void main(String[] args){
MyLinkedList<String> list = new MyLinkedList<String>();
list.add("Element 0");
list.add("Element 1");
list.add("Element 2");
Iterator<String> iter = list.iterator();
System.out.println(iter.next());
System.out.println(iter.next());
System.out.println(iter.next());
for (String s : list){
System.out.println(s);
}
}
}
And everything works except the last part, when trying to compile it I get a error saying error: for-each not applicable to expression type for (String s : list)
Is there something obvious I have overlooked in the implementation?
Here is the rest of my code, I am using custom Interfaces for Iterable and List
interface List<T> extends Iterable<T> {
public int size();
public void add(int pos, T x);
public void add(T x);
}
interface Iterator<T> {
boolean hasNext();
T next();
}
interface Iterable<T> {
Iterator<T> iterator();
}
And here is the main part of the code
import java.util.* ;
class MyLinkedList<T> implements List<T> {
private Node<T> head;
private Node<T> tail;
private int currentSize;
//constructor for class
public MyLinkedList(){
this.head = null;
this.tail = null;
this.currentSize = 0;
}
//Node class used to hold the information, and link to each other
public class Node<E> {
private E data;
private Node<E> next;
//constructor for node class
public Node(E data, Node<E> next){
this.data = data;
this.next = next;
}
public E getData(){
return this.data;
}
public void setData(E newData){
this.data = newData;
}
public Node<E> getNext(){
return this.next;
}
public void setNext(Node<E> newNext){
this.next = newNext;
}
}
class LinkedListIterator implements Iterator<T>{
private Node<T> current;
public LinkedListIterator(){
current = head;
}
public T next(){
if (current == null){
throw new NoSuchElementException();
}
T temp = current.getData();
current = current.getNext();
return temp;
}
public boolean hasNext(){
return current != null;
}
}
public Iterator<T> iterator(){
return new LinkedListIterator();
}
public int size(){
return this.currentSize;
}
public boolean isEmpty(){
return this.size() == 0;
}
public void add(int pos, T x){
if(pos < 0 || pos > size()){
throw new IndexOutOfBoundsException();
}
if(pos == size()){
add(x);
return;
}
if (pos == 0){
head = new Node(x, head);
}else{
Node<T> current = head;
for(int j = 0; j < pos-1; j++){
current = current.getNext();
}
current.setNext(new Node(x, current.getNext()));
}
currentSize++;
}
public void add(T x){
if(isEmpty()){
head = new Node(x, null);
tail = head;
}else{
tail.setNext(new Node(x, null));
tail = tail.getNext();
}
currentSize++;
}
}
It's because you have provided your own implementation of Iterable. For the for-each to work, you have to implement java.util.Iterable
Related
I'm trying to construct a single linked list. The single linked list has a method, addLast, that adds a node to the tail of the linked list. I created a *LList2 *class to store the first and last node of the list.
The error occurs when I try to use the addLast method in the driver class. Below is my code. Any suggestions would be helpful!
`
// Part One Question 2,3
public class SingleLinkedListWorkSheetQ2Q3{
public static void main (String[] args){
ListNode<Integer> rear = new ListNode<>(0, null);
ListNode<Integer> list = new ListNode<>(1, rear);
list = new ListNode<>(2, list);
list = new ListNode<>(3, list);
LList2 <Integer> temp = new LList2 <> (list, rear);
temp.printWhile();
temp.addLast(new ListNode<Integer> (-2, null));
}
}
class ListNode <E> {
private E val;
private ListNode <E> next;
public ListNode(E val, ListNode <E> next){
this.val = val;
this.next = next;
}
public E getVal(){
return val;
}
public ListNode <E> getNext(){
return next;
}
public void updateNext(ListNode <E> node){
next = node;
}
}
class LList2 <E> {
private ListNode <E> front;
private ListNode <E> rear;
public LList2(ListNode <E> front, ListNode <E> rear){
this.front = front;
this.rear = rear;
}
public void printWhile(){
System.out.print("[");
while(front != null){
System.out.print(front.getVal() + ", ");
front = front.getNext();
}
System.out.print("]");
}
public void printFor(){
System.out.print("[");
for(ListNode <E> temp = front; temp != null; temp = temp.getNext()){
System.out.print(temp.getVal() + ", ");
}
System.out.print("]");
}
// obj represents value
public void addFirst(E obj){
front = new ListNode<E>(obj, front);
if(front.getNext() == null){
rear = front;
}
}
public void addLast(E obj){
if(rear != null)
rear.updateNext(new ListNode<E>(obj, null));
else{
rear = new ListNode<E>(obj, null);
front = rear;
}
}
}
`
Because you were using the Generic Types Java compiler will erase all E to the Integer type, so you can't set the ListNode<Integer>
the code will be this:
package com.github.lemon.office;
import joptsimple.internal.Strings;
public class SingleLinkedListWorkSheetQ2Q3 {
public static void main(String[] args) {
ListNode<Integer> rear = new ListNode<>(0, null);
ListNode<Integer> list = new ListNode<>(1, rear);
list = new ListNode<>(2, list);
list = new ListNode<>(3, list);
LList2<Integer> temp = new LList2<>(list, rear);
temp.printWhile();
temp.addLast(-2);
temp.printWhile();
}
}
class ListNode<E> {
private final E val;
private ListNode<E> next;
public ListNode(E val, ListNode<E> next) {
this.val = val;
this.next = next;
}
public E getVal() {
return val;
}
public ListNode<E> getNext() {
return next;
}
public boolean hasNext() {
return next != null;
}
public void updateNext(ListNode<E> node) {
next = node;
}
}
class LList2<E> {
private ListNode<E> front;
private ListNode<E> rear;
public LList2(ListNode<E> front, ListNode<E> rear) {
this.front = front;
this.rear = rear;
}
public void printWhile() {
StringBuilder sb = new StringBuilder("[");
for (ListNode<E> temp = front; temp != null; temp = temp.getNext()) {
sb.append(temp.getVal());
if (temp.hasNext()) {
sb.append(",");
}
}
sb.append("]");
System.out.println(sb);
}
public void printFor() {
System.out.print("[");
for (ListNode<E> temp = front; temp != null; temp = temp.getNext()) {
System.out.print(temp.getVal() + ", ");
}
System.out.print("]");
}
// obj represents value
public void addFirst(E obj) {
front = new ListNode<E>(obj, front);
if (front.getNext() == null) {
rear = front;
}
}
public void addLast(E obj) {
if (rear != null)
rear.updateNext(new ListNode<E>(obj, null));
else {
rear = new ListNode<E>(obj, null);
front = rear;
}
}
}
So im following along this playlist about data structures and in this video to conclude the linked list part, the professor explain we need an inner class called IteratorHelper.
Video:
https://www.youtube.com/watch?v=bx0ebSGUKto&list=PLpPXw4zFa0uKKhaSz87IowJnOTzh9tiBk&index=21
This is the code in my github with the linked list implementation and the main class called tester:
https://github.com/Ghevi/Algos-DataStructures/tree/master/src/com/ghevi/ads/linkedlists
The problem is that the tester class can't compile. If I instantiate the linked list as an ListIterator i can't access its methods. I also can't iterate trough it regardless of having the IteratorHelper inner class.
In the video he writes "implements ListI<>" is just a shorter version for ListIterator<>?
Sorry im just a beginner.
package com.ghevi.ads.linkedlists;
import java.util.ListIterator;
public class Tester {
public static void main(String[] args) {
ListIterator<Integer> list = new LinkedList<Integer>();
int n = 10;
for (int i = 0; i < n; i++)
list.addFirstWithTail(i);
int removedFirst = list.removeFirst();
int removedLast = list.removeLast();
for(int x : list){
System.out.println(x);
}
}
}
The video is not very clear, but basically LinkedList should implement Iterable, not ListIterator. IteratorHelper should implement ListIterator (see 4:20 timestamp).
Here's the fixed code:
package linkedlists;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
// Notes at Notes/Singly LinkedList.txt
public class LinkedList<E> implements Iterable<E> {
#Override
public Iterator<E> iterator() {
return new IteratorHelper();
}
class IteratorHelper implements ListIterator<E>{
Node<E> index;
public IteratorHelper(){
index = head;
}
// Return true if there is an element to return at the pointer
#Override
public boolean hasNext() {
return (index != null);
}
// Return the element where the pointer is and mover the pointer to the next element
#Override
public E next() {
if(!hasNext())
throw new NoSuchElementException();
E val = index.data;
index = index.next;
return val;
}
#Override
public boolean hasPrevious() {
return false;
}
#Override
public E previous() {
return null;
}
#Override
public int nextIndex() {
return 0;
}
#Override
public int previousIndex() {
return 0;
}
#Override
public void remove() {
}
#Override
public void set(E e) {
}
#Override
public void add(E e) {
}
/* For version older than java 1.8
public void remove(){
throw new UnsupportedOperationException();
}
public void forEachRemaining(){};
*/
} // inner class (can only be accessed by the outer class)
class Node<E> {
E data;
Node<E> next;
public Node(E obj){
data = obj;
next = null;
}
} // inner class (can only be accessed by the outer class)
private Node<E> head;
private Node<E> tail;
private int currentSize;
public LinkedList(){
head = null;
tail = null;
currentSize = 0;
}
public void addFirst(E obj){
Node<E> node = new Node<E>(obj);
// The order of these 2 lines is fundamental
node.next = head;
head = node;
currentSize++;
}
public void addFirstWithTail(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
return;
}
// The order of these 2 lines is fundamental
node.next = head;
head = node;
currentSize++;
}
// O(n)
public void slowAddLast(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
currentSize++;
return;
}
Node<E> tmp = head;
while(tmp.next != null){
tmp = tmp.next;
}
tmp.next = node;
currentSize++;
}
// O(1)
public void fasterAddLast(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
currentSize++;
return;
}
tail.next = node;
tail = node;
currentSize++;
}
public E removeFirst(){
if(head == null){
return null;
}
E tmp = head.data;
if(head == tail){
head = tail = null;
} else {
head = head.next;
}
currentSize--;
return tmp;
}
public E removeLast(){
if(head == null){
return null;
}
if(head == tail){
return removeFirst();
}
Node<E> current = head; // Can also write Node<E> current = head, previous = null;
Node<E> previous = null;
while(current != tail){
// The order is crucial
previous = current;
current = current.next;
}
previous.next = null;
tail = previous;
currentSize--;
return current.data;
}
public E findAndRemove(E obj){
Node<E> current = head, previous = null;
// In an empty list current = null so we skip to the last line
while(current != null){
if(((Comparable<E>)obj).compareTo(current.data) == 0){
// Beginning or single element
if(current == head)
return removeFirst();
// Ending of the list
if(current == tail)
return removeLast();
currentSize--;
// Removing the reference to the node to delete
previous.next = current.next;
return current.data;
}
previous = current;
current = current.next;
}
// Node not found
return null;
}
public boolean contains(E obj){
Node<E> current = head;
while(current != null) {
if(((Comparable<E>) obj).compareTo(current.data) == 0)
return true;
current = current.next;
}
return false;
}
public E peekFirst(){
if(head == null)
return null;
return head.data;
}
public E peekLast(){
if(tail == null)
return null;
return tail.data;
}
}
The interface methods hasPrevious, next, etc... have been moved into the IteratorHelper class which implements Iterator. The LinkedList class has an iterator() method because it implements Iterable. Now you can instantiate a LinkedList object and iterate over it in a for-loop:
package linkedlists;
public class Tester {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
int n = 10;
for (int i = 0; i < n; i++)
list.addFirstWithTail(i);
int removedFirst = list.removeFirst();
int removedLast = list.removeLast();
for(int x : list){
System.out.println(x);
}
}
}
Here's a handy chart to remind you which class should have which functions:
More on Iterable vs Iterator
I am learning java and i am still a beginner.i have written this code to implement a circular linked list and it keeps printing the numbers when i try to print the list. it looks like some kind of an infinite loop maybe. I even tried to use a debug but it didn't do much for me. I would very much appreciate it if you could review the code and see why this is happening. here is the code below. I would be also for giving me feedback on the code :)
this is the class for the circular linked list
public class CircularLinkedList<E> implements API<E> {
private Node<E> head;
private int size = 0;
public void placeAtBeginning(E element) {
Node<E> newNode = new Node<E>(element);
if(head == null) {
head = newNode;
head.setNext(head);
}else {
Node<E> temp = head;
head = newNode;
newNode.setNext(temp);
}
size++;
}
public void placeAtEnd(E element) {
Node<E> newNode = new Node<E>(element);
if (head == null) {
head = newNode;
}else {
Node<E> temp = head;
while (temp.getNext() != head) {
temp = temp.getNext();
}
temp.setNext(newNode);
}
newNode.setNext(head);
size++;
}
public void deleteFromBeginning() {
Node<E> temp = head;
while (temp.getNext() != head) {
temp = temp.getNext();
}
temp.setNext(head.getNext());
head = head.getNext();
size --;
}
public void deleteFromEnd() {
Node<E> temp = head;
while(temp.getNext().getNext() != head) {
temp = temp.getNext();
}
temp.setNext(head);
size--;
}
public void print() {
Node<E> temp = head;
while(temp.getNext()!= head) {
System.out.print(temp.getValue() + " , ");
temp = temp.getNext();
}
System.out.print(temp.getValue());
}
}
this is the class for my node
public class Node<T> {
private Node<T> next;
private T item;
public Node(T item) {
this.item = item;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return this.next;
}
public T getValue() {
return this.item;
}
}
this is my main where i tried to test it using int.
public class Main {
public static void main(String [] args) {
API <Integer> list = new CircularLinkedList<Integer>();
int a = 10;
int b = 3;
int c = 15;
int d = 8;
int f = 9;
list.placeAtBeginning(a);
list.placeAtEnd(b);
list.print();
System.out.println();
list.placeAtBeginning(c);
list.placeAtBeginning(d);
list.print();
}
}
this is my API which I used
public interface API <E> {
public void placeAtBeginning(E element);
public void placeAtEnd(E element);
public void deleteFromBeginning();
public void deleteFromEnd();
public void print();
}
Your method placeAtBeginning() doesn't insert the new element in the circular list but simply lets the next of the new element refer to the original circular list.
Try this:
public void placeAtBeginning(E element)
{
Node<E> newNode = new Node<E>(element);
if(head == null)
{
head = newNode;
head.setNext(head);
}
else
{
Node<E> last = head;
while (last.getNext() != head)
last = last.getNext();
newNode.setNext(head);
head = newNode;
last.setNext(head);
}
size++;
}
I didn't check the other methods. They might contain a similar error.
I have created a doubly-linked list and implemented my own iterator.
However, I have done something wrong and my iterator results in endless loop.
Have been struggling to find the error, so any feedback is much appreciated. Thanks in advance. I apologise for the wall of code, I think the error lies within my iterator of the way I have created my Node class.
My Code:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyDoubleEndedLinkedList<T extends Comparable<T>> implements
Iterable<T> {
// initialising Nodes including the two sentinal nodes
private Node<T> head;
private Node<T> tail;
private Node<T> current;
private int currentsize;
MyDoubleEndedLinkedList() {
head = new Node<T>();
tail = new Node<T>();
head.setNext(tail);
tail.setPrevious(head);
current = head;
currentsize = 0;
// Methods used to help loop and iterate through the list
public boolean isEmpty() {
return (current == head && current == tail);
}
public boolean endList() {
return (current != tail);
}
public void resetCurrent() {
current = head;
}
public void nextCurrent() {
current = current.getNext();
}
public T getCurrent() {
return current.getData();
}
public int size() {
return this.currentsize;
}
#Override
public Iterator<T> iterator() {
return new LinkedListIterator<T>();
}
// Node class for doublyLinkedList
public class Node<E> {
private Node<E> previous;
private Node<E> next;
private E data;
Node() {
previous = null;
next = null;
data = null;
}
Node(Node<E> newPrevious, Node<E> newNext, E newData) {
previous = newPrevious;
next = newNext;
data = newData;
}
// set previous node
public void setPrevious(Node<E> newPrevious) {
previous = newPrevious;
}
// set Next node
public void setNext(Node<E> newNext) {
next = newNext;
}
public void setData(E newData) {
data = newData;
}
public Node<E> getPrevious() {
return previous;
}
public Node<E> getNext() {
return next;
}
public E getData() {
return data;
}
}
class LinkedListIterator<E> implements Iterator<T> {
private Node<T> current;
private Node<T> previous;
private Node<T> previous2;
private boolean removeCalled;
public LinkedListIterator() {
current = head;
previous = null;
previous2 = null;
removeCalled = false;
}
public boolean hasNext() {
return (current != null);
}
public T next() {
if (hasNext()) {
T temp = current.getData();
previous2 = previous;
previous = current;
current = current.next;
removeCalled = false;
return temp;
}
throw new NoSuchElementException();
}
public void remove() {
if (previous == null || removeCalled) {
throw new IllegalStateException();
}
if (previous2 == null) {
head = current;
} else {
previous2.setNext(current);
previous = previous2;
}
removeCalled = true;
throw new UnsupportedOperationException();
}
}}
So i can't find the bug in your code but here is a simpler implementation of a basic linked list in Java. If you show me how you're adding elements to the list it would be easier to track down.
import java.util.Iterator;
public class MyLinkedList<T> implements Iterable<T> {
private Node head = null;
private Node tail = null;
public static void main(String[] args) {
MyLinkedList<String> li = new MyLinkedList<>();
li.add("1");
li.add("2");
li.add("3");
li.add("4");
li.add("5");
for (String s : li) {
System.out.println(s);
}
}
public void add(T data) {
if (head == null) {
head = new Node(data, null);
tail = head;
} else {
Node n = new Node(data, tail);
tail.next = n;
tail = n;
}
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
T data = current.data;
current = current.next;
return data;
}
#Override
public void remove() {
}
};
}
class Node {
final T data;
Node prev = null;
Node next = null;
Node(T data, Node prev) {
this.data = data;
this.prev = prev;
}
}
}
I want to write implementation of Deque
I have written code below but unfortunately I have a problem with it
when I use addFirst and addLast or even removeFirst every thing is ok
but when I use removelast the programs throws NullPointerException
I dont know what is the problem exactly so I got really confused
Can Anyone plaese Help me??
Thanks in advance for your attention
Node Class::
public class Node<E>{
E element;
Node<E> prev , next;
public Node(E element, Node<E> prev, Node<E> next) {
this.element = element;
this.prev = prev;
this.next = next;
}
public Node() {
this(null, null, null);
}
public void setNext(Node next)
{
this.next = next;
}
public void setPrev(Node prev)
{
this.prev = prev;
}
public Node getNext()
{
return next;
}
public Node getPrev()
{
return prev;
}
}
here is Deque Interface::
public interface DQ<E> {
public int size();
public boolean isEmpty();
public E getFirst();
public E getLast();
public void addFirst (E element);
public void addLast (E element);
public E removeFirst();
public E removeLast();
}
and finally here is MyDQ Class which implements DQ class::
public class MyDQ<E> implements DQ<E>{
Node<E> head , tail;
int size = 0;
#Override
public int size() {
return size;
}
#Override
public boolean isEmpty() {
return size == 0;
}
#Override
public E getFirst() {
if(head == null)
return null;
return head.element;
}
#Override
public E getLast() {
if(head == null)
return null;
return tail.element;
}
#Override
public void addFirst(E element) {
Node<E> n = new Node<>(element, null, null);
if(head == null)
head = tail = n;
else
{
head.setPrev(n);
n.setNext(head);
head = n;
}
size++;
}
#Override
public void addLast(E element) {
Node<E> n = new Node<>(element, null, null);
if(head == null)
head = tail = n;
else
{
tail.setNext(n);
n.setPrev(head);
tail = n;
}
size++;
}
#Override
public E removeFirst() {
if(head == null)
return null;
Node<E> n = head;
head = head.getNext();
head.setPrev(null);
n.setNext(null);
size --;
return n.element;
}
#Override
public E removeLast() {
if(head == null)
return null;
Node<E> n = tail;
tail = tail.getPrev();
tail.setNext(null);
n.setPrev(null);
size --;
return n.element;
}
}
I created a simple Person object to use:
public class Person {
String name;
Integer age;
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
}
I tested this using the following unit test:
#Test
public void testOneElementDeque() {
MyDQ<Person> deq = new MyDQ<>();
Person p1 = new Person("John", 12);
Person p2 = new Person("Eric", 45);
deq.addLast(p1);
assertEquals(p1, deq.getLast());
assertEquals(p1, deq.getFirst());
deq.removeLast();
}
This throws a null pointer at this line(line 78):
tail.setNext(null);
By this point in the call tail has been set to null by this line:
tail = tail.getPrev();
To correct this I rewrote the implementaion to null check tail at this point:
public E removeLast() {
if(tail == null)
return null;
Node<E> n = tail;
tail = tail.getPrev();
if(tail != null)
tail.setNext(null);
n.setPrev(null);
size --;
return n.element;
}