Friday, November 09, 2012

Python's enumerate for Java

Surprisingly I did not find Python's enumerate in Guava Iterables.

A little static import and all is well:

import com.google.common.collect.UnmodifiableIterator;

import javax.annotation.Nonnull;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Iterator;
import java.util.Map.Entry;

/**
 * {@code EnumerateIterable} wraps an iterable like Python {@code enumerate}.
 *
 * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
 */
public final class EnumerateIterable<T>
        implements Iterable<Entry<Integer, T>> {
    @Nonnull
    private final Iterable<T> delegate;

    public EnumerateIterable(@Nonnull final Iterable<T> delegate) {
        this.delegate = delegate;
    }

    /**
     * Creates a new enumerated iterable for the given <var>delegate</var>.
     *
     * @param delegate the underlying iterable, never missing
     * @param <T> the underlying wrapped type
     *
     * @return the new enumerated iterable, never missing
     */
    @Nonnull
    public static <T> Iterable<Entry<Integer, T>> enumerate(@Nonnull final Iterable<T> delegate) {
        return new EnumerateIterable<>(delegate);
    }

    @Nonnull
    @Override
    public Iterator<Entry<Integer, T>> iterator() {
        return new EnumerateIterator<>(delegate);
    }

    private static final class EnumerateIterator<T>
            extends UnmodifiableIterator<Entry<Integer, T>> {
        @Nonnull
        private final Iterator<T> it;
        int i;

        EnumerateIterator(@Nonnull final Iterable<T> delegate) {
            it = delegate.iterator();
            i = 0;
        }

        @Override
        public boolean hasNext() {
            return it.hasNext();
        }

        @Override
        @Nonnull
        public Entry<Integer, T> next() {
            return new SimpleImmutableEntry<>(i++, it.next());
        }
    }
}

UPDATE: Completeness requires a static factory method for arrays as well as iterables.

No comments: