Java - DoublyLinkedList Iterator implementation - java

I have implemented a DoublyLinkedList, as follows:
public class DoublyLinkedList<E> implements Iterable<E> {
protected static class Node<E> {
private E element;
private Node<E> prev;
private Node<E> next;
public Node(E e, Node<E> p, Node<E> n) {
element = e;
prev = p;
next = n;
}
public void setNext(Node<E> n) {
next = n;
}
}
protected Node<E> header;
protected Node<E> trailer;
private int size = 0;
public DoublyLinkedList() {
header = new Node<>(null, null, null);
trailer = new Node<>(null, header, null);
header.setNext(trailer);
}
Now I'm trying to implement an iterator and this is the solution I came up with:
private class DLLIterator implements Iterator<E> {
private Node<E> cursor = header;
#Override
public boolean hasNext() {
return cursor != null;
}
#Override
public E next() {
if (!hasNext()) throw new NoSuchElementException("No next element.");
E element = cursor.getElement();
cursor = cursor.getNext();
return element;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove not supported.");
}
}
It seems correct, but I'm having a lot of doubts about the hasNext() method and the initial cursor assignment. Shouldn't it be
public boolean hasNext() {
return cursor.getNext() != null;
}
?
Otherwise, it seems to me that the iterator will get me two null elements, trying to fetch them from the header and trailer. Should I change the method?

#Jorn Vernee's comment contains the right answer:
Changing the implementation would just complicate things, e.g. what if
the header passed in is null? hasNext would trow NPE. It wouldn't
return any null elements either, since it checks if the current Node
is null before returning it (unless, of course, that Node contains
null).

Related

Node<> and toString() methods when finding elements and creating new lists

Not sure how to fill in the last two methods at the bottom of this code. The findNode(E e) should return the Node that contains the element e, or it returns null if the list is empty. The last toString() method is meant to override a previous one in another class and prints the content of a list.
public class DoublyLinkedList<E> {
public static class Node<E> {
private E element; // reference to the element stored at
private Node<E> prev; // reference to the previous node in the
private Node<E> next; // reference to the subsequent node in
public Node(E element, Node<E> prev, Node<E> next) {
this.element = element;
this.prev = prev;
this.next = next;
}
// public accessor methods
public E getElement() {
return element;
}
public Node<E> getPrev() {
return prev;
}
public Node<E> getNext() {
return next;
}
// Update methods
public void setPrev(Node<E> p) {
prev = p;
}
public void setNext(Node<E> n) {
next = n;
}
} //----------- end of nested Node class -----------
// instance variables of the DoublyLinkedList
private Node<E> header; // header sentinel
private Node<E> trailer; // trailer sentinel
private int size = 0; // number of elements in the list
public DoublyLinkedList() {
header = new Node<>(null, null, null); // create header
trailer = new Node<>(null, header, null); // trailer is preceded by
header.setNext(trailer); // header is followed by
}
// public accessor methods
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer); // place just before the
}
// public update methods
public void addBetween(E e, Node<E> predecessor, Node<E> successor) {
// create and link a new node
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
size++;
}
public Node<E> findNode(E e) {
E element = e;
if (isEmpty()) {
return null;
}
int node = 0;
Node<E> temp = header;
while (temp != null) {
if (temp.getNext() == element) {
return node;
}
node++;
temp = temp.getNext();
}
}
public String toString() {
ArrayList<E> ref = new ArrayList<>();
int counter = 1;
return ref.toString();
}
}

How can I change my Iterator to be a Fast-fail Iterator?

I'm trying to understand how to modify the Iterator of my Linked List to be fail-fast.
I understand what it means for an Iterator to be fail-fast, but I don't know how exactly should I change my implementation to achieve this behavior.
I was thinking about adding a key so for every add, but I don't think it is good enough. It is the first time I'm trying to implement a fail-fast iterator, and I would really appreciate any hint.
My code:
package GenericLinkedList;
import java.util.Iterator;
public class GenericLinkedList<E> implements Iterable<E> {
private Node<E> head;
public void pushFront(E data){
head = new Node<>(data, head);
}
public E popFront(){
E dataHead = head.data;
head = head.next;
return dataHead;
}
public int size(){
int counter = 0;
for(E element : this){
++counter;
}
return counter;
}
public boolean isEmpty(){
return (null == head);
}
public Iterator<E> find(E data){
IteratorIMP iter = new IteratorIMP(head);
for(E element : this){
if(element.equals(data)){
return iter;
}
iter.next();
}
return null;
}
public static <E> GenericLinkedList<E> merge(GenericLinkedList<E> firstList, GenericLinkedList<E> secondList){
GenericLinkedList<E> mergeList = new GenericLinkedList<E>();
for(E element : firstList){
mergeList.pushFront(element);
}
for(E element : secondList){
mergeList.pushFront(element);
}
return newReverse(mergeList);
}
public static <E> GenericLinkedList<E> newReverse(GenericLinkedList<E> list){
GenericLinkedList<E> reverseList = new GenericLinkedList<E>();
for(E element : list){
reverseList.pushFront(element);
}
return reverseList;
}
private static class Node<T> {
private Node<T> next;
private T data;
private Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
}
private class IteratorIMP implements Iterator<E> {
Node<E> node;
private IteratorIMP(Node<E> start){
node = start;
}
#Override
public boolean hasNext() {
return (node != null);
}
#Override
public E next() {
E data = node.data;
node = node.next;
return data;
}
}
#Override
public Iterator<E> iterator() {
IteratorIMP iter = new IteratorIMP(head);
return iter;
}
}
Fail-fast implementation of the Iterator insures that it would raise an exception if there's an evidence that the collection is being structurally modified (an element was added or removed) during the iteration process, because in such a case, iterator might not be able to reflect the actual state of the collection.
The common approach is to introduce two counters of modifications:
one as the instance field of the list modCount, which would be incremented whenever list gets modified via pushFront(), popFront(), etc.
another in the Iterator - expectedModCount.
If during the next() call turns out that modCount and expectedModCount variables are not equal, that means that there has been a modification after the iterator was created. In such a case, fail-fast Iterators from the JDK would throw ConcurrentModificationException.
public class GenericLinkedList<E> implements Iterable<E> {
private Node<E> head;
private int modCount;
public void pushFront(E data) {
modCount++; // list is being modified - incrementing the count
head = new Node<>(data, head);
}
public E popFront() {
modCount++; // list is being modified - incrementing the count
E dataHead = head.data;
head = head.next;
return dataHead;
}
// ...
private class IteratorIMP implements Iterator<E> {
private Node<E> node;
private final int expectedModCount;
private IteratorIMP(Node<E> start) {
this.node = start;
this.expectedModCount = GenericLinkedList.this.modCount;
}
// ...
#Override
public E next() {
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
E data = node.data;
node = node.next;
return data;
}
}
}

java.lang.AbstractMethodError: Method DoublyLinkedList.isEmpty()Z is abstract?

My toString() method at the bottom is giving me the above error when trying to test for an empty DoublyLinkedList in my main method also at the bottom. My intuition tells me that this may be caused by the List interface that I'm implementing since the word "List" is underlined in red reading "The type List is already defined" and the isEmpty() method is pulled from that interface. Not entirely sure though. Hope this isn't a burden to anyone. Thanks in advance.
public class DoublyLinkedList<T> implements List<T> {
/**
* Node is a pair containing a data field and a pointers to
* the previous and next nodes in the list.
*/
class Node {
T data;
Node next, prev;
Node(T data) {
this(data, null, null);
}
Node(T data, Node prev, Node next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
Node head; // always points to the headnode for this list
int n; // the number of nodes in this list, initially 0
/**
* Creates the empty list.
*/
public DoublyLinkedList() {
// TODO: Create the headnode.
// Note that the prev and next fields in the headnode should
// point back to the headnode.
Node head = new Node(null);
head.prev=head;
head.next=head;
}
public String toString() {
System.out.println("meeee");
if (this.isEmpty())
return "()";
Iterator<T> it = iterator();
StringBuilder ans = new StringBuilder("(").append(it.next());
while (it.hasNext())
ans.append(" ").append(it.next());
return ans.append(")").toString();
}
public static void main(String... args) {
DoublyLinkedList<Integer> xs = new DoublyLinkedList<>();
System.out.println(xs.toString());
}
interface List<T> extends Iterable<T> {
void add(T x); // simple add
T remove(int i);
T get(int i);
boolean contains(T x);
int size();
default boolean isEmpty() {
return size() == 0;
}
}

java iterator could not be applied to for_each

I try to build an Linked Positional List myself when learning Data Structures and Algorithms in Java 6th Edition.
Position implements Node to store data.
I want to build two iterators,one for iterating Position and another for iterate the element in the Position. So I think two kinds of for-each loop could be applied as the following:
LinkedPositionalList<String> list = new LinkedPositionalList<>();
list.addFirst("A");
list.addLast("B");
list.addLast("V");
for (Position posi : list.positions()) {
}
for (String str:list ) {
}
It turns out that the second for-each not applicable to type,but the first one works well. So how to make the second for-each iterator work?
This is my code for building such class:
p.s.:The code is very long.The last part of nested class tried to implement the Iterator interface.The code before that is the way to build Linked Positional List which I think is not important...
public class LinkedPositionalList<E> implements PositionalList<E> {
private static class Node<E> implements Position<E> {
private E element;
private Node<E> prev;
private Node<E> next;
public Node(E e, Node<E> p, Node<E> n) {
element=e;
prev=p;
next=n;
}
public E getElement() throws IllegalStateException {
if (next == null) {
throw new IllegalStateException("Position no longer valid");
}
return element;
}
public Node<E> getPrev() {
return prev;
}
public Node<E> getNext() {
return next;
}
public void setElement(E e) {
element=e;
}
public void setPrev(Node<E> prev) {
this.prev = prev;
}
public void setNext(Node<E> next) {
this.next=next;
}
}
private Node<E> header;
private Node<E> trailer;
private int size=0;
public LinkedPositionalList() {
header = new Node<>(null, null, null);
trailer = new Node<>(null, header, null);
header.setNext(trailer);
}
private Node<E> validate(Position p)throws IllegalArgumentException {
if (!(p instanceof Node)) {
throw new IllegalArgumentException("Invalid p");
}
Node<E> node=(Node<E>)p;
if (node.getNext() == null) {
throw new IllegalArgumentException("p is no longer in the list");
}
return node;
}
private Position<E> position(Node<E> node) {
if (node == header || node == trailer) {
return null;
}
return node;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public Position<E> first() {
return position(header.getNext());
}
public Position<E> last() {
return position(trailer.getPrev());
}
public Position<E> before(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getPrev());
}
public Position<E> after(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getNext());
}
public Position<E> addBetween(E e, Node<E> pred, Node<E> succ) {
Node<E> newest = new Node<>(e, pred, succ);
pred.setNext(newest);
succ.setPrev(newest);
size++;return newest;
}
public Position<E> addFirst(E e) {
return addBetween(e, header, header.getNext());
}
public Position<E> addLast(E e) {
return addBetween(e, trailer.getPrev(), trailer);
}
public Position<E> addBefore(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e, node.getPrev(), node);
}
public Position<E> addAfter(Position<E> p,E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e,node,node.getNext());
}
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E answer = node.getElement();
node.setElement(e);
return answer;
}
public E remove(Position<E> p)throws IllegalArgumentException {
Node<E> node = validate(p);
Node<E> pre = node.getPrev();
Node<E> succ = node.getNext();
pre.setNext(succ);
succ.setPrev(pre);
size--;
E answer = node.getElement();
node.setNext(null);
node.setPrev(null);
node.setElement(null);
return answer;
}
//Here is the part that I think should be redesigned!!!!
private class PositionIterator implements Iterator<Position<E>> {
private Position<E> cursor = first(); // position of the next element to report
private Position<E> recent = null; // position of last reported element
public boolean hasNext() { return (cursor != null); }
public Position<E> next() throws NoSuchElementException {
if (cursor == null) throw new NoSuchElementException("nothing left");
recent = cursor; // element at this position might later be removed
cursor = after(cursor);
return recent;
}
public void remove() throws IllegalStateException {
if (recent == null) throw new IllegalStateException("nothing to remove");
LinkedPositionalList.this.remove(recent); // remove from outer list
recent = null; // do not allow remove again until next is called
}
} //------------ end of nested PositionIterator class ------------
//---------------- nested PositionIterable class ----------------
private class PositionIterable implements Iterable<Position<E>> {
public Iterator<Position<E>> iterator() { return new PositionIterator(); }
} //------------ end of nested PositionIterable class ------------
public Iterable<Position<E>> positions() {
return new PositionIterable(); // create a new instance of the inner class
}
//---------------- nested ElementIterator class ----------------
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> posIterator = new PositionIterator();
public boolean hasNext() { return posIterator.hasNext(); }
public E next() { return posIterator.next().getElement(); } // return element!
public void remove() { posIterator.remove(); }
}
public Iterator<E> iterator() { return new ElementIterator(); }
}
For the built-in Java Collection Framework classes, if you just want the items, use:
for (String item : list) {
// do something with item
}
To use an explicit iterator (so you could, for instance, use the iterator's remove() method), you use a regular for loop:
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
String item = iter.next();
// do something with item
}
Of course, you can also use a while loop.
For your particular class, it's hard to tell if the above applies because you haven't posted the definition of PositionalList.
Replace the inner loop with:
for (String str : list) {
}
That is the correct syntax for the Java for-each loop.

Singly Linked list remove bool method

Im trying to create a public bool remove(E element) method that removes the first node that includes the element and if no such a node is found it returns false otherwise true...How can I do that ? im having trouble linking the removed node's predecessor to its successor to close the gap created by the node's removal...this is my code so far...thank you
public class SinglyLinkedList<E> {
private final SLNode<E> head;
private final SLNode<E> tail;
int length;
// creates an empty list
public SinglyLinkedList() {
head = new SLNode<E>();
tail = new SLNode<E>();
head.setSuccessor(tail);
length = 0;
}
// adds new node on beginning of the list
public void add(E element) {
SLNode<E> node = new SLNode<E>(element, null);
node.setSuccessor(head.getSuccessor());
head.setSuccessor(node);
}
// adds new node on beginning of the list
public void add(SLNode<E> node) {
node.setSuccessor(head.getSuccessor());
head.setSuccessor(node);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
SLNode<E> cursor = head.getSuccessor();
while (cursor != tail) {
sb.append(cursor.getElement()).append(" ");
cursor = cursor.getSuccessor();
}
sb.append("\n");
return sb.toString();
}
}
slnode class
public class SLNode<E> {
private E element;
private SLNode<E> successor;
public SLNode() {
element = null;
successor = null;
}
public SLNode(E theElement, SLNode<E> theSuccessor) {
element = theElement;
successor = theSuccessor;
}
public E getElement() {
return element;
}
public void setElement(E newElement) {
element = newElement;
}
public SLNode<E> getSuccessor() {
return successor;
}
public void setSuccessor(SLNode<E> newSuccessor) {
successor = newSuccessor;
}
}
The trick is as you iterate, you need to keep a reference to both the previous and the current element. The reference to the previous element is what lets you close the gap:
public boolean remove(E element) {
SLNode<E> previous = head;
SLNode<E> current = head.getSuccessor();
while (current != tail) {
if (current.getElement().equals(element)) {
previous.setSuccessor(current.getSuccessor());
return true;
}
previous = current;
current = current.getSuccessor();
}
return false;
}

Categories

Resources