Erweiterte For-Schleife mit Index - II

In meinem vorigen Beitrag zum Thema habe ich die Kritik geerntet, dass bei jedem Schleifendurchlauf ein neues Objekt erzeugt werden muss. Folgende Lösung ist ziemlich „hacky“, vermeidet aber die Objekterzeugung.

import java.util.Iterator;
 
public class IndexedIterable<T> implements Iterable<T> {
 
    private final Iterator<T> iterator;
    private int index = -1;
    private boolean used = false;
 
    public IndexedIterable(final Iterable<T> iterable) {
        iterator = new Iterator<T>() {
            private Iterator<T> delegate = iterable.iterator();
            public boolean hasNext() { return delegate.hasNext(); }
            public T next() { index++;  return delegate.next();  }
            public void remove() { throw new UnsupportedOperationException(); }
        };
    }
 
    @Override
    public Iterator<T> iterator() {
        if (used) {
            throw new IllegalStateException("can't be reused");
        }
        used = true;
        return iterator;
    }
 
    public int getIndex() {  return index; }
 
    public static <T> IndexedIterable<T> indexed(Iterable<T> iterable) {
        return new IndexedIterable<>(iterable);
    }
}

Verwenden kann man die Klasse so:

List<String> list =...
IndexedIterable<String> ii = IndexedIterable.indexed(list);
for(String s : ii) {
      System.out.println(ii.getIndex() + ". " + s);
}

Unschön ist, dass man eine IndexedIterable-Variable außerhalb der Schleife braucht, und dass diese nicht wiederverwendet werden darf (sie explodiert dann mit einem kleinen Rauchwölkchen). Diese Nachteile rechtfertigen den Einsatz wohl nur, wenn es um wirklich große Datenmengen und das letzte Quentchen Performance geht.

Weiterlesen…