How to Write Our Own Iterator in Java

Can we write our own iterator in Java?

Sure. An iterator is just an implementation of the java.util.Iterator interface. If you're using an existing iterable object (say, a LinkedList) from java.util, you'll need to either subclass it and override its iterator function so that you return your own, or provide a means of wrapping a standard iterator in your special Iterator instance (which has the advantage of being more broadly used), etc.

How to create a custom Iterator in Java?

A minimal example would be to return an empty iterator, whose hasNext() always returns false and next() will throw NoSuchElementException.

public Iterator<Foo> iterator() {
return new Iterator<Foo>() {
public boolean hasNext() {
return false;
}
public Foo next() {
throw new NoSuchElementException();
}
};
}

Of course most iterators have states. For example you can iterate from 0 to the integer value the Foo instance holds.

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Foo implements Iterable<Foo> {
private final int value;

public Foo(final int value) {
this.value = value;
}

@Override
public Iterator<Foo> iterator() {
return new Iterator<Foo>() {
private Foo foo = new Foo(0);

@Override
public boolean hasNext() {
return foo.value < Foo.this.value;
}

@Override
public Foo next() {
if (!hasNext()) throw new NoSuchElementException();

Foo cur = foo;
foo = new Foo(cur.value+1);
return cur;
}
};
}

public static void main(String[] args) {
Foo foo = new Foo(10);
for (Foo f: foo) {
System.out.println(f.value);
}
}
}

How to create a custom iterator for a deck of cards? (Java)

Add this to class Deck implements Iterable<Card>

public Card getCard( int i ){
return deck[i];
}

public Iterator<Card> iterator(){
return new DeckIterator( this );
}

public class DeckIterator implements Iterator<Card> {
private Deck d;
private int pos;
DeckIterator( Deck d ){
this.d = d;
}

@Override
public boolean hasNext(){
return pos < d.deck.length;
}

@Override
public Card next(){
if( pos >= d.deck.length ){
throw new NoSuchElementException( "no more cards in deck" );
}
return d.getCard( pos++ );
}

@Override
public void remove(){
throw new UnsupportedOperationException( "not implemented" );
}
}

Suit might be iimplemented as an enum, as might rank.

How to implement iterator as an attribute of a class in Java

Its very unusual to maintain an iterator as an instance variable of the class. You can only traverse the array once - probably not what you want. More likely, you want your class to provide an iterator to anyone that wants to traverse your array. A more traditional iterator is below.

Java 5+ code - I haven't tried to compile or run, so it may be contain errors (not near a dev machine right now). It also uses autobox'ing for converting Integer to int.

public class MyArray implements Iterable<Integer> {

public static class MyIterator implements Iterator<Integer> {

private final MyArray myArray;
private int current;

MyIterator(MyArray myArray) {
this.myArray = myArray;
this.current = myArray.start;
}

@Override
public boolean hasNext() {
return current < myArray.end;
}

@Override
public Integer next() {
if (! hasNext()) throw new NoSuchElementException();
return myArray.arr[current++];
}

@Override
public void remove() {
// Choose exception or implementation:
throw new OperationNotSupportedException();
// or
//// if (! hasNext()) throw new NoSuchElementException();
//// if (currrent + 1 < myArray.end) {
//// System.arraycopy(myArray.arr, current+1, myArray.arr, current, myArray.end - current-1);
//// }
//// myArray.end--;
}
}

....

// Most of the rest of MyArray is the same except adding a new iterator method ....

public Iterator<Integer> iterator() {
return new MyIterator();
}

// The rest of MyArray is the same ....

}

Also note: be careful of not hitting that 500 element limit on your static array. Consider using the ArrayList class instead if you can.

Java custom iterator for linked list

Your implementation of LinkedListIterator is correct, the problem is in the toString() method.
You are calling this.iterator() 3 times, so each time you return a new instance of LinkedListIterator.
Instead you have to call this.interator() only once and use the instance you get.
Like this:

    Iterator<String> it=this.iterator();
while (it.hasNext()) {
System.out.println(it.hasNext());
output += it.next() + "\n";
}

Regarding the new question.

If you instantiate the private Iterator<String> linkedListIterator attribute in the body of the class, (Something that should never be done), every time you refer to it you will make a call to the public Iterator<String> iterator() method and you will get a new instance of LinkedListIterator.

You are making the same mistake as in the beginning.
This is an example of why attributes should be instantiated only within a method declaration.

Remember that an iterator can only move forward, if you want to restart it you must create a new instance. That's what you do by calling this.iterator().


I recommend you to use some debugging tools so you can see the instructions that are executed

Also, there is a design pattern that deals iterators.
https://en.wikipedia.org/wiki/Iterator_pattern



Related Topics



Leave a reply



Submit