How to wrap Java util. Iterator to change the type of the object being iterated
I'm providing some appearance classes for third-party APIs. I need to wrap an iterator so that I can replace things iterated with my own appearance object
This is a simplified version of my facade class, which wraps an API class called item
class FacadeItem { Item item; FacadeItem(Item item) { this.item = item; } }
The API provides the iterator iterator < item > in this form
I need to implement this form of iterator. Iterator < facade item > is supported by the iterator of API
I consider using the forwardingiterator in the guava library as follows:
class FacadeItemIterator<FacadeItem> extends ForwardingIterator<Item> { final Iterator<Item> delegate; // backing iterator FacadeItemIterator(Iterator<Item> delegate) { this.delegate = delegate; } @Override protected Iterator<Item> delegate() { return delegate; } @Override public FacadeItem next() { return new FacadeItem(super.next()); } }
However, the compiler does not allow overriding next () because it expects to return an item instead of a facade item
Solution
The iterator interface is not so large, so you can write your own delegate iterator:
class FacadeIterator implements Iterator<FacadeItem> { private final Iterator<Item> delegate; // set in ctor @Override public FacadeItem next() { return new FacadeItem(delegate.next()); } // the other two methods just delegate straight }
then
Iterator<FacadeItem> facadeIterator = new FacadeIterator(itemIterator);
If you are using guava, you can use their iterators The transform static method makes one for you:
Iterator<FacadeItem> facadeIterator = Iterators.transform(itemIterator,/* anon class of Function<Item,FacadeItem> */);
In Java 1.8, this option becomes very simple:
Iterator<FacadeItem> facadeIterator = Iterators.transform(itemIterator,FacadeItem::new)