If I have a list containing [alice, bob, abigail, charlie]
and I want to write an iterator such that it iterates over elements that begin with 'a', can I write my own ? How can I do that ?

- 60,010
- 15
- 145
- 220

- 3,531
- 9
- 30
- 31
-
4You can. You have to implement the Iterator interface. – gd1 May 01 '11 at 15:03
-
sure, it's just a normal interface. Proxying java.util for a JDO impl. involves quite a lot of custom iterators. – bestsss May 01 '11 at 16:27
-
http://codereview.stackexchange.com/questions/48109/simple-example-of-an-iterable-and-an-iterator-in-java – Ciro Santilli OurBigBook.com Dec 09 '15 at 11:58
6 Answers
The best reusable option is to implement the interface Iterable and override the method iterator().
Here's an example of a an ArrayList like class implementing the interface, in which you override the method Iterator().
import java.util.Iterator;
public class SOList<Type> implements Iterable<Type> {
private Type[] arrayList;
private int currentSize;
public SOList(Type[] newArray) {
this.arrayList = newArray;
this.currentSize = arrayList.length;
}
@Override
public Iterator<Type> iterator() {
Iterator<Type> it = new Iterator<Type>() {
private int currentIndex = 0;
@Override
public boolean hasNext() {
return currentIndex < currentSize && arrayList[currentIndex] != null;
}
@Override
public Type next() {
return arrayList[currentIndex++];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
This class implements the Iterable interface using Generics. Considering you have elements to the array, you will be able to get an instance of an Iterator, which is the needed instance used by the "foreach" loop, for instance.
You can just create an anonymous instance of the iterator without creating extending Iterator and take advantage of the value of currentSize to verify up to where you can navigate over the array (let's say you created an array with capacity of 10, but you have only 2 elements at 0 and 1). The instance will have its owner counter of where it is and all you need to do is to play with hasNext(), which verifies if the current value is not null, and the next(), which will return the instance of your currentIndex. Below is an example of using this API...
public static void main(String[] args) {
// create an array of type Integer
Integer[] numbers = new Integer[]{1, 2, 3, 4, 5};
// create your list and hold the values.
SOList<Integer> stackOverflowList = new SOList<Integer>(numbers);
// Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
for(Integer num : stackOverflowList) {
System.out.print(num);
}
// creating an array of Strings
String[] languages = new String[]{"C", "C++", "Java", "Python", "Scala"};
// create your list and hold the values using the same list implementation.
SOList<String> languagesList = new SOList<String>(languages);
System.out.println("");
// Since our class SOList is an instance of Iterable, then we can use it on a foreach loop
for(String lang : languagesList) {
System.out.println(lang);
}
}
// will print "12345
//C
//C++
//Java
//Python
//Scala
If you want, you can iterate over it as well using the Iterator instance:
// navigating the iterator
while (allNumbers.hasNext()) {
Integer value = allNumbers.next();
if (allNumbers.hasNext()) {
System.out.print(value + ", ");
} else {
System.out.print(value);
}
}
// will print 1, 2, 3, 4, 5
The foreach documentation is located at http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html. You can take a look at a more complete implementation at my personal practice google code.
Now, to get the effects of what you need I think you need to plug a concept of a filter in the Iterator... Since the iterator depends on the next values, it would be hard to return true on hasNext(), and then filter the next() implementation with a value that does not start with a char "a" for instance. I think you need to play around with a secondary Interator based on a filtered list with the values with the given filter.

- 62,887
- 36
- 269
- 388

- 21,361
- 14
- 77
- 80
-
18
-
4
-
3It's a good practice to throw unsupported operation exception from us implemented methods. I think it's a good idea to throw unsupported operation exception from remove() method ! – darshan Jun 28 '14 at 16:03
-
2Sorry @darshan, but this solution is in regards to "how to write iterators"... If the focus was to "write perfectly written code", that would be there! – Marcello DeSales Sep 15 '14 at 21:54
-
1not clear why 'arrayList[currentIndex] != null' check is required inside hasNext(). can someone please explain. – Bhushan Karmarkar Jun 07 '19 at 11:25
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.

- 1,031,962
- 187
- 1,923
- 1,875
-
9good answer.... +1 However you're not forced to subclass LinkedList. You can write a CustomIterator that it's instantiated with new CustomIterator(somelist), since interfaces tell nothing about constructors. – gd1 May 01 '11 at 15:21
-
1@Giacomo: That's what I meant by *"... or provide a means of wrapping a standard iterator in your special `Iterator` instance..."* (and thanks). :-) – T.J. Crowder May 01 '11 at 15:45
Good example for Iterable to compute factorial
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Short code for Java 1.8
new FactorialIterable(5).forEach(System.out::println);
Custom Iterable class
public class FactorialIterable implements Iterable<Integer> {
private final FactorialIterator factorialIterator;
public FactorialIterable(Integer value) {
factorialIterator = new FactorialIterator(value);
}
@Override
public Iterator<Integer> iterator() {
return factorialIterator;
}
@Override
public void forEach(Consumer<? super Integer> action) {
Objects.requireNonNull(action);
Integer last = 0;
for (Integer t : this) {
last = t;
}
action.accept(last);
}
}
Custom Iterator class
public class FactorialIterator implements Iterator<Integer> {
private final Integer mNumber;
private Integer mPosition;
private Integer mFactorial;
public FactorialIterator(Integer number) {
this.mNumber = number;
this.mPosition = 1;
this.mFactorial = 1;
}
@Override
public boolean hasNext() {
return mPosition <= mNumber;
}
@Override
public Integer next() {
if (!hasNext())
return 0;
mFactorial = mFactorial * mPosition;
mPosition++;
return mFactorial;
}
}

- 9,477
- 4
- 61
- 77

- 5,277
- 4
- 36
- 47
This is the complete code to write an iterator such that it iterates over elements that begin with 'a':
import java.util.Iterator;
public class AppDemo {
public static void main(String args[]) {
Bag<String> bag1 = new Bag<>();
bag1.add("alice");
bag1.add("bob");
bag1.add("abigail");
bag1.add("charlie");
for (Iterator<String> it1 = bag1.iterator(); it1.hasNext();) {
String s = it1.next();
if (s != null)
System.out.println(s);
}
}
}
Custom Iterator class
import java.util.ArrayList;
import java.util.Iterator;
public class Bag<T> {
private ArrayList<T> data;
public Bag() {
data = new ArrayList<>();
}
public void add(T e) {
data.add(e);
}
public Iterator<T> iterator() {
return new BagIterator();
}
public class BagIterator<T> implements Iterator<T> {
private int index;
private String str;
public BagIterator() {
index = 0;
}
@Override
public boolean hasNext() {
return index < data.size();
}
@Override
public T next() {
str = (String) data.get(index);
if (str.startsWith("a"))
return (T) data.get(index++);
index++;
return null;
}
}
}

- 956
- 9
- 33
- 56
You can implement your own Iterator. Your iterator could be constructed to wrap the Iterator returned by the List, or you could keep a cursor and use the List's get(int index) method. You just have to add logic to your Iterator's next method AND the hasNext method to take into account your filtering criteria. You will also have to decide if your iterator will support the remove operation.

- 6,774
- 1
- 35
- 37
Here is the complete answer to the question.
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
class ListIterator implements Iterator<String>{
List<String> list;
int pos = 0;
public ListIterator(List<String> list) {
this.list = list;
}
@Override
public boolean hasNext() {
while(pos < list.size()){
if (list.get(pos).startsWith("a"))
return true;
pos++;
}
return false;
}
@Override
public String next() {
if (hasNext())
return list.get(pos++);
throw new NoSuchElementException();
}
}
public class IteratorTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("alice", "bob", "abigail", "charlie");
ListIterator itr = new ListIterator(list);
while(itr.hasNext())
System.out.println(itr.next()); // prints alice, abigail
}
}
ListIterator
is the iterator for the array which returns the elements that start with 'a'.- There is no need for implementing an Iterable interface. But that is a possibility.
- There is no need to implement this generically.
- It fully satisfies the contract for hasNext() and next(). ie if hasNext() says there are still elements, next() will return those elements. And if hasNext() says no more elements, it returns a valid
NoSuchElementException
exception.

- 13,456
- 15
- 82
- 98
-
I think your implementation looses the main advantage of iterators which is constant time complexity of hasNext() and next() – Ayoub Omari Oct 16 '20 at 11:39
-
@Quade. hasNext and next never can be constant time both. Imagine a list with no match. The list has to be iterated all the way till figuring out there is not match. How can that be constant? – apadana Oct 16 '20 at 16:43
-
Nice answer, and actually, the `next` should still run in constant time (depending on the list implementation though). And @Ayoub Omari, the while loop introduced in the `hasNext` is an unavoidable computation that has to be done at some point anyways to shift the position for filtering, so having that done in the `hasNext` method is the same as doing the filtering outside of the iterator. You would have had to code that either way – Lorenzo Jan 11 '21 at 15:42