Download as pdf or txt
Download as pdf or txt
You are on page 1of 3

Chapter 102: Iterator and Iterable

The java.util.Iterator is the standard Java SE interface for object that implement the Iterator design pattern.
The java.lang.Iterable interface is for objects that can provide an iterator.

Section 102.1: Removing elements using an iterator


The Iterator.remove() method is an optional method that removes the element returned by the previous call to
Iterator.next(). For example, the following code populates a list of strings and then removes all of the empty
strings.

List<String> names = new ArrayList<>();


names.add("name 1");
names.add("name 2");
names.add("");
names.add("name 3");
names.add("");
System.out.println("Old Size : " + names.size());
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String el = it.next();
if (el.equals("")) {
it.remove();
}
}
System.out.println("New Size : " + names.size());

Output :

Old Size : 5
New Size : 3

Note that is the code above is the safe way to remove elements while iterating a typical collection. If instead, you
attempt to do remove elements from a collection like this:

for (String el: names) {


if (el.equals("")) {
names.remove(el); // WRONG!
}
}

a typical collection (such as ArrayList) which provides iterators with fail fast iterator semantics will throw a
ConcurrentModificationException.

The remove() method can only called (once) following a next() call. If it is called before calling next() or if it is
called twice following a next() call, then the remove() call will throw an IllegalStateException.

The remove operation is described as an optional operation; i.e. not all iterators will allow it. Examples where it is not
supported include iterators for immutable collections, read-only views of collections, or fixed sized collections. If
remove() is called when the iterator does not support removal, it will throw an UnsupportedOperationException.

Section 102.2: Creating your own Iterable


To create your own Iterable as with any interface you just implement the abstract methods in the interface. For

GoalKicker.com – Java® Notes for Professionals 576


Iterable there is only one which is called iterator(). But its return type Iterator is itself an interface with three
abstract methods. You can return an iterator associated with some collection or create your own custom
implementation:

public static class Alphabet implements Iterable<Character> {

@Override
public Iterator<Character> iterator() {
return new Iterator<Character>() {
char letter = 'a';

@Override
public boolean hasNext() {
return letter <= 'z';
}

@Override
public Character next() {
return letter++;
}

@Override
public void remove() {
throw new UnsupportedOperationException("Doesn't make sense to remove a letter");
}
};
}
}

To use:

public static void main(String[] args) {


for(char c : new Alphabet()) {
System.out.println("c = " + c);
}
}

The new Iterator should come with a state pointing to the first item, each call to next updates its state to point to
the next one. The hasNext() checks to see if the iterator is at the end. If the iterator were connected to a modifiable
collection then the iterator's optional remove() method might be implemented to remove the item currently
pointed to from the underlying collection.

Section 102.3: Using Iterable in for loop


Classes implementing Iterable<> interface can be used in for loops. This is actually only syntactic sugar for getting
an iterator from the object and using it to get all elements sequentially; it makes code clearer, faster to write end
less error-prone.

public class UsingIterable {

public static void main(String[] args) {


List<Integer> intList = Arrays.asList(1,2,3,4,5,6,7);

// List extends Collection, Collection extends Iterable


Iterable<Integer> iterable = intList;

// foreach-like loop
for (Integer i: iterable) {

GoalKicker.com – Java® Notes for Professionals 577


System.out.println(i);
}

// pre java 5 way of iterating loops


for(Iterator<Integer> i = iterable.iterator(); i.hasNext(); ) {
Integer item = i.next();
System.out.println(item);
}
}
}

Section 102.4: Using the raw iterator


While using the foreach loop (or "extended for loop") is simple, it's sometimes beneficial to use the iterator directly.
For example, if you want to output a bunch of comma-separated values, but don't want the last item to have a
comma:

List<String> yourData = //...


Iterator<String> iterator = yourData.iterator();
while (iterator.hasNext()){
// next() "moves" the iterator to the next entry and returns it's value.
String entry = iterator.next();
System.out.print(entry);
if (iterator.hasNext()){
// If the iterator has another element after the current one:
System.out.print(",");
}
}

This is much easier and clearer than having a isLastEntry variable or doing calculations with the loop index.

GoalKicker.com – Java® Notes for Professionals 578

You might also like