One of the most widely-anticipated and useful language updates in Java 5 was the introduction of a “foreach” construct, to reduce the amount of boilerplate code which needs to be written when a programmer wants to iterate over all the elements in a collection. Languages such as C# and PHP have had the feature for a long time, and Java programmers were clamouring for it too.
The syntax looks like:
for (element foo : collection) {
...
}
To allow your own classes to be iterated over with the foreach construct they must implement the new Iterable interface and thus provide an “iterator()” method to return the appropriate Iterator object.
However, there is a limitation in the current implementation. In some code I was writing I found I had a class which looked like:
public class Foo {
private List<Integer> intList = new ArrayList<Integer>();
private List<Float> floatList = new ArrayList<Float>();
}
I wanted the user of Foo to be able to choose to iterate over either the intList or floatList. My first attempt was:
public class Foo implements Iterable<Integer>, Iterable<Float> {
private List<Integer> intList = new ArrayList<Integer>();
private List<Float> floatList = new ArrayList<Float>();
public Iterator<Integer> iterator() {
return intList.iterator();
}
public Iterator<Float> iterator() {
return floatList.iterator();
}
}
But it won’t compile! The problem is that you are not permitted to implement the same interface more than once, even if you use a different generic type each time.
I’m not sure why this is, but I guess it has something to do with the requirement to support legacy code without modification. It meant that being able to write:
Foo foo;
for (Integer i : foo) {
...
}
for (Float f : foo) {
...
}
was impossible.
I thought about this for a day or two until a solution popped into my head (after a few beers, as often happens!). It is possible if we use Java’s support for inner classes. The code isn’t quite as simple, but it’s the best we can do – and the difference to the user is so small that I think it’s a neat solution. The code follows:
public class Foo {
private List<Integer> intList = new ArrayList<Integer>();
private List<Float> floatList = new ArrayList<Float>();
public class Integers implements Iterable<Integer> {
public Iterator<Integer> iterator() {
return intList.iterator();
}
}
public class Floats implements Iterable<Float> {
public Iterator<Float> iterator() {
return floatList.iterator();
}
}
}
The user code looks like:
Foo foo;
for (Integer i : foo.new Integers()) {
...
}
for (Float f : foo.new Floats()) {
...
}
I’m quite pleased with this solution. I wouldn’t go as far as to call it a design pattern, but it certainly allows us to work around one of the limitations of Java generics.