java iterator could not be applied to for_each - java

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.

Related

How do I add elements (integers or string) in the middle of my doubly-linked list? -Java

This code allows me to create a linked list and I want to be able to add elements
between two nodes.
I'm having trouble understanding how to set it up so I can insert a number between 40 and 30.
public class DoublyLinkedList<E> {
private static class Node<E> {
//Node Fields
private E element;
private Node<E> prev;
private Node<E> next;
// Node Constructor
public Node(E e, Node<E> p, Node<E> n) {
this.element = e;
this.prev = p;
this.next = n;
}
// Node Methods
public E getElement() {
return element;
}
public Node<E> getPrev() {
return this.prev;
}
public Node<E> getNext() {
return this.next;
}
public void setPrev(Node<E> p) {
this.prev = p;
}
public void setNext(Node<E> n) {
this.next = n;
}
}
// DLinkedList Fields
private Node<E> header;
private Node<E> trailer;
int size;
// DLinkedList Constructor
public DoublyLinkedList() {
this.header = new Node<>(null, null, null);
this.trailer = new Node<>(null, this.header, null);
this.header.setNext(this.trailer);
}
// DLinkedList Methods
public int size() {
return this.size;
}
public E first() {
if (isEmpty()) {
return null;
}
return this.header.next.getElement();
}
public E last() {
if (isEmpty()) {
return null;
}
return this.trailer.prev.getElement();
}
public boolean isEmpty() {
return size == 0;
}
public void addFirst(E e) {
addBetween(e, this.header, this.header.getNext());
}
public void addLast(E e) {
addBetween(e, this.trailer.getPrev(), this.trailer);
}
public void addBetween(E e, Node<E> predecessor, Node<E> successor) {
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
this.size++;
}
public E removeFirst() {
if (this.isEmpty()) {
return null;
}
return this.remove(header.getNext());
}
public E removeLast() {
if (this.isEmpty()) {
return null;
}
return this.remove(trailer.getPrev());
}
public E remove(Node<E> e) {
e.next.setPrev(e.prev);
e.prev.setNext(e.next);
this.size--;
return e.getElement();
}
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = this.header.next;
while (walk != this.trailer) {
sb.append(walk.element);
if (walk.next != this.trailer)
sb.append("--> ");
walk = walk.next;
}
sb.append(")");
return sb.toString();
}
// Node myList = new Node<E>(null, trailer, header);
// myList.e.addFirst
// Node myList2 = new Node<E>(null, 1, null);
}
class Main {
public static void main(String[] args) {
// create a DoublyLinkedList object
DoublyLinkedList Node = new DoublyLinkedList();
// Add nodes to the list
Node.addFirst(10);
Node.addFirst(20);
Node.addFirst(30);
Node.addFirst(40);
Node.addFirst(50);
Node.removeFirst();
Node.removeLast();
//Node.addBetween(Node, null, null);
// print the nodes of DoublyLinkedList
System.out.println(Node);
}
}
Start by changing addBetween to return the node.
public Node<E> addBetween(E e, Node<E> predecessor, Node<E> successor) {
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
this.size++;
return newest;
}
Change addFirst and addLast to return that node. I'll only show addFirst:
public Node<E> addFirst(E e) {
return addBetween(e, this.header, this.header.getNext());
}
Save the nodes for 30 and 40:
Node<Integer> node30 = Node.addFirst(30);
Node<Integer> node40 = Node.addFirst(40);
Then you can use addBetween:
Node.addBetween(newNumber, node30, node40);
You need not expose the class Node and indeed you made it private.
But then you cannot navigate by Node, just by E. So remove(Node) is not possible as public method.
Node's methods could be private too.
Node need not be parametrized by <E>. That can even give serious programming problems, as there then are two Es. Remove it.
addBetween is nicely symmetric, but successor is redundant. I would remove it as parameter and make it a local variable.
Rename the local variable Node to list.
So:
private E removeNode(Node node) {
node.next.setPrev(node.prev);
node.prev.setNext(node.next);
size--;
return node.getElement();
}
private Optional<Node> find(E element) {
for (Node node = header.next; node != trailer; node = node.next) {
if (node.element == element) {
return Optional.of(node);
}
}
return Optional.empty();
}
public boolean remove(E e) {
Optional<Node> nodeOpt = find(e);
nodeOpt.ifPresent(n -> removeNode(n));
return nodeOpt.isPresent();
}
The same for an insertBefore(E), insertAfter(E).

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();
}
}

Return top element in a stack

I am struggling with the top() method that is supposed to retrieve the top element of the stack, or return null if this stack is empty and return the top element of the stack. How can fix the loop?
public class Stack<E> implements IStack<E> {
Node head;
public E top() {
if (head == null)
return null;
Node<E> tempNode = head;
for (int i = 0; i < size; i++) {
if (tempNode.getmNextNode() == null) {
tempNode.getmElement();
}
tempNode = tempNode.getmNextNode();
}
return tempNode.getmElement();
}
}
My Node class:
public class Node<E> {
private E mElement;
private Node<E> mNextNode;
Node(E data) {
this.setmElement(data);
}
public E getmElement() {
return this.mElement;
}
public void setmElement(E element) {
this.mElement = element;
}
public Node<E> getmNextNode() {
return this.mNextNode;
}
public void setmNextNode(Node<E> node) {
this.mNextNode = node;
}
}
public E top() {
if (head == null)
return null;
Node<E> tempNode = head;
while(tempNode.getmNextNode()!=null) {
tempNode = tempNode.getmNextNode();
}
return tempNode.getmElement();
}
Your top() method is supposed to return the last pushed element into the stack and not the first one. When pushing a new element, the head is referenced to this element. Thus, the head is the top element and would be then returned by your method.
public class Stack<E> implements IStack<E>{
public E top() {
if(head==null){
throw new StackEmptyException();
}
return head.getmElement();
}
}

Java - DoublyLinkedList Iterator implementation

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).

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