Friday, August 11, 2006

Read-only enhanced for loops in Java

I was just commenting on Paul Holser's blog about this small idiom using the Java enhanced for loop:

for (final T t : unmodifiable(collection)) {
    doSomethingWith(t);
}

The plumbing is simple:

public static <T> Iterable<T> unmodifiable(
        final Collection<T> c) {
    return new Iterable<T>() {
        public Iterator<T> iterator() {
            // Presuming a static decorator method
            // akin to Collections.unmodifiableCollection()
            return unmodifiableIterator(c.iterator());
        }
    };
}

Naturally, I wish Sun would add something like this to java.util.Collections, but I am sure they get many, many requests for JDK additions. Adding in a cleaned up Jakarta Collections library would help.

Another example of this sort of thing is a filterable iterator:

for (final T t : filter(collection, filter) {
    // Only works on collection elements
    // accepted by the filter.
    doSomethingWith(t);
}

Anyway, Paul has a lot of interesting ideas in store for Jaggregate 3.0.

UPDATE: An anonymous commenter made the observation that an immutable Iterable is useless in an enhanced for loop. D'oh! I should not have overlooked that point when I used the enhanced for loop in my examples. However, the read-only property is still useful when you call iterator().

5 comments:

gumi said...

This is implemented in JGA.

Anonymous said...

What does this accomplish? Enhanced for loops don't expose the iterator, so they can't modify the collection anyway.

Brian Oxley said...

You know... you are right. I was thinking about Iterator and added Iterable out of habit.

Anonymous said...

Why won't the unmodifiable methods in the Collections class do what you want?

Brian Oxley said...

Re: Collections.unmodifiable(Collection).

You could, of course, use that. I presented the Iterator more as example code when all you want is an Iteratable and not a full Collection interface. Less is more, as they say.