My framework is full of iterators like
int n = col.getSize();
for (int i = 0 ; i != n; i++) {
Type obj = col.get(i);
And, I feel that every program that iterates items over the index has a piece of code like this. It feels ugly compared to the neat foreach
for (Type obj : col) {
Transition to foreach requires making all the collections Iterable, which means creating a new Iterator in every iterator() method. Now, I had the ugly code in every collection declaration instead of its use places. So, I did the a good job, I moved the ugly code into the common.utils.
public abstract class ImmutableIterator<T> implements Iterator<T> {
private int i = 0;
private final int size = getSize();
public abstract int getSize(); // to be implemented by user
public abstract T getValue(int i); // to be implemented by user
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return getValue(i++);
}
public boolean hasNext() { return i != size;}
public void remove() {
throw new UnsupportedOperationException("Remove is not implemented");
}
}
Now, I have isolated this ugly pattern in only place. This is the best I could do. The collections will supply the size and value(i). The only problem is performance penaly: I have to do the size check twice in the loop, first for hasNext and another in the next(). I wonder why Sun does not provide such a class? It is needed to everybody. Have I just overlooked it?
Tomasz Nurkiewicz directed us to the Guava’s
UnmodifiableIterator. But, only remove method is defined there whereas we want the index iteration also. This hint allowed LouisWasserman to find out a better solution: theAbstractIndexedListIteratordoes what we want. The only drawback is that this class does not implement the remove method and is closed in the Guava package. All this tells us that such classes are really useful but must be implemented by the user in his framework.JB Nizet proposed another solution. Instead of implementing the iterator interface on top of getSize/GetItem(idx) methods, we can return one retreived from the underlying collection.