Sunday, June 25, 2006

Iterable and for

I love the fact that there's a new interface in java.util: Iterable. Why you might ask? Could it be for the new shorthand for?

List someList = ... ;
for (SomethingCool each : someList) {
...
}

Well, that would be one reason to get excited. Close, but no cigar, no, I like the fact that the method iterator() has been split from java.util.Collection. It allows one to have infinite collections. Most of the time, you don't care how large the collection is, you just want to traverse over its elements. Iterable allows you to do just that. All you care about is that it can produce elements. This means if you have a large file, you could read it in chunks without anyone being the wiser. They would just have an Iterable object and not know how things worked in the back end. Encapsulation at its finest.

String insanelyLargeFileName=...;
RecordReader reader=RecordReader.on(insanelyLargeFileName);
for (Record each : reader) {
...do something cool with each record...
}
class RecordReader implements Iterable {
...
}

The client of RecordReader knows nothing about how many records are read in from the file at once nor should they care. They just want each record. We could for example read in 500 records in at a time or just one. It doesn't matter. We could even pass how many to read in at once as an argument to on. Throttling is left to us as a performance enhancement in one class.

Iterables allow us to have true object streams. How cool is that! For giggles, we could have also implemented it totally differently. This time I return an Iterable when asked instead of making the RecordReader implement it. I like this approach much better.

String insanelyLargeFileName=...;
RecordReader reader=RecordReader.on(insanelyLargeFileName);
for (Record each : reader.records()) {
...do something cool with each record...
}
class RecordReader{
...
public Iterable records() {
...
}
}

The naive (or simplest) implementation of records() could simply return the entire collection of the file using an ArrayList. And when the file got too big, then move to a custom Iterable object that could read in chunks of the file. By putting iterator() into its own interface, we got a greater flexibility beyond the nice new for sugar. Polymorphism is a wonderful thing wouldn't you agree?

I use Iterables all over the place in my Reflective Testing Framework to traverse over classes, class path items, and methods. It allowed me to have a nice pipes and filters pattern throughout the code. It also made it easy for others to extend what I have done. Have fun! Iterable might be the best new feature of Java5.

No comments: