PUBLIC OBJECT

Coding in the small with Google Collections: AbstractIterator

Part 17 in a Series.

I really like the Java Collections API. So much so, that I use 'em when I'm doing work that isn't particularly collectioney. For example, I recently wrote a quick-n-dirty app that rewrote some files line-by-line. Instead of using a Reader as input, I used an Iterator<String>. The easiest way to create such an iterator is to load the entire file into memory first.

Before:

  public Iterator<String> linesIterator(Reader reader) {
    BufferedReader buffered = new BufferedReader(reader);
    List<String> lines = new ArrayList<String>();

    try {
      for (String line; (line = buffered.readLine()) != null; ) {
        lines.add(line);
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    return lines.iterator();
  }`</pre>That code is simple, but inefficient. And it won't work if the file doesn't fit into memory. A better approach is to implement `Iterator` and to read through the file on-demand as the lines are requested. Google Collections ' [AbstractIterator](http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/AbstractIterator.html) makes this easy. Whenever a new line is requested, it gets called back to read it from the stream.

### After:
<pre class="prettyprint">`  public Iterator&lt;String&gt; linesIterator(Reader reader) {
    final BufferedReader buffered = new BufferedReader(reader);

    return new AbstractIterator&lt;String&gt;() {
      protected String computeNext() {
        try {
          String line = buffered.readLine();
          return line != null ? line : endOfData();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };
  }

This class is really takes the fuss out of custom iterators. Now it's not difficult to create iterators that compute a series, process a data stream, or even compose other iterators.