如何包装java.util.Iterator以更改正在迭代的对象的类型

Gle*_*nce 3 java collections guava iterator-facade

我正在为第三方API提供一些外观类,我需要包装一个迭代器,以便我可以替换用我自己的外观对象迭代的东西.

这是我的facade类的简化版本,它包装了一个名为Item的API类

class FacadeItem {
    Item item;
    FacadeItem(Item item) {
        this.item = item;
    }
}
Run Code Online (Sandbox Code Playgroud)

API提供此表单的迭代器 Iterator<Item>

我需要实现此形式Iterator<FacadeItem>的迭代器,该迭代器由API的迭代器支持.

我考虑过如下使用Guava库中的ForwardingIterator:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

next()编译器不允许覆盖,因为它期望返回的类型是Item,而不是FacadeItem

ysh*_*vit 11

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
}
Run Code Online (Sandbox Code Playgroud)

然后

Iterator<FacadeItem> facadeIterator = new FacadeIterator(itemIterator);
Run Code Online (Sandbox Code Playgroud)

如果你正在使用Guava,你可以使用他们的Iterators.transform静态方法为你制作其中一个:

Iterator<FacadeItem> facadeIterator = Iterators.transform(itemIterator,
    /* anon class of Function<Item, FacadeItem> */);
Run Code Online (Sandbox Code Playgroud)

在Java 1.8中,这个选项变得非常简单:

Iterator<FacadeItem> facadeIterator
    = Iterators.transform(itemIterator, FacadeItem::new)
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.为了完整起见,我稍后会提到那些后来可能会出现的问题,你需要在第一个解决方案中覆盖的"其他两个方法"是hasNext()和remove() (2认同)