Over a million developers have joined DZone.

How to Implement an Iterating Adapter

· Java Zone

Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code! Brought to you in partnership with ZeroTurnaround.

Iterator is one of the fundamental Java interfaces, introduced in Java 1.2. It is supposed to be very simple; however, in my experience, many Java developers don't understand how to implement a custom one, which should iterate a stream of data coming from some other source. In other words, it becomes an adapter of another source of data, in the form of an iterator. I hope this example will help.

Let's say we have an object of this class:

final class Data {
  byte[] read();
}

When we call read(), it returns a new array of bytes that were retrieved from somewhere. If there is nothing to retrieve, the array will be empty. Now, we want to create an adapter that would consume the bytes and let us iterate them:

final class FluentData implements Iterator<Byte> {
  boolean hasNext() { /* ... */ }
  Byte next() { /* ... */ }
  void remove()  { /* ... */ }
}

Here is how it should look (it is not thread-safe!):

final class FluentData implements Iterator<Byte> {
  private final Data data;
  private final Queue<Byte> buffer = new LinkedList<>();
  public FluentData(final Data dat) {
    this.data = dat;
  }
  public boolean hasNext() {
    if (this.buffer.isEmpty()) {
      for (final byte item : this.data.read()) {
        this.buffer.add(item);
      }
    }
    return !this.buffer.isEmpty();
  }
  public Byte next() {
    if (!this.hasNext()) {
      throw new NoSuchElementException("Nothing left");
    }
    return this.buffer.poll();
  }
  public void remove() {
    throw new UnsupportedOperationException("It is read-only");
  }
}

There is no way to make it thread-safe because the iterating process is outside the scope of the iterator. Even if we declare our methods as synchronized, this won't guarantee that two threads won't conflict when they both call hasNext() and next(). So don't bother with it and just document the iterator as not thread-safe, then let its users synchronize one level higher when necessary.


The Java Zone is brought to you in partnership with ZeroTurnaround. Check out this 8-step guide to see how you can increase your productivity by skipping slow application redeploys and by implementing application profiling, as you code!

Topics:
java

Published at DZone with permission of Yegor Bugayenko, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}