-4

我的框架充满了迭代器,比如

int n = col.getSize();
for (int i = 0 ; i != n; i++) {
  Type obj = col.get(i);

而且,我觉得每个在索引上迭代项目的程序都有一段这样的代码。与整洁的 foreach 相比,感觉很难看

for (Type obj : col) {

转换到 foreach 需要使所有集合都可迭代,这意味着在每个 iterator() 方法中创建一个新的迭代器。现在,我在每个集合声明中都有丑陋的代码,而不是它的使用位置。所以,我做得很好,我把丑陋的代码移到了 common.utils 中。

public abstract class ImmutableIterator<T> implements Iterator<T> {
    private int i = 0; 
    private final int size = getSize();

    public abstract int getSize();  // to be implemented by user
    public abstract T getValue(int i); // to be implemented by user

    public T next() { 
        if (!hasNext()) throw new NoSuchElementException(); 
        return getValue(i++);
    }

    public boolean hasNext() { return i != size;}

    public void remove() {
        throw new UnsupportedOperationException("Remove is not implemented");
    }
}

现在,我在唯一的地方隔离了这个丑陋的模式。这是我能做的最好的。集合将提供大小和值(i)。唯一的问题是性能损失:我必须在循环中进行两次大小检查,第一次是 hasNext,另一个是 next()。我想知道为什么 Sun 不提供这样的类?每个人都需要它。我只是忽略了它吗?

4

2 回答 2

1

在抽象类中共享的代码非常少,因此抽象几乎没有带来什么好处。我认为在每个集合中从头开始实现这样的迭代器同样容易。在许多情况下,hasNext可能可以更直接地实施,例如。

看,你的抽象类的抽象行与非抽象代码行一样多。现在,许多类可能想要实现可变迭代器,那么您的抽象类中几乎没有任何东西。

另外,它永远不需要改变。如果抽象类允许您进行一次更改(例如错误修复)并同时修复多个类,则它特别棒。但是,这段代码如此简单,这会是什么错误呢?例如,“删除”中的“抛出”几乎没有错误 - 它永远不应该被执行。在多个迭代器之间共享它根本没有任何好处。

于 2012-11-23T19:57:33.683 回答
0

Tomasz Nurkiewicz 将我们带到 Guava's UnmodifiableIterator。但是,这里只定义了 remove 方法,而我们也想要索引迭代。这个提示让 LouisWasserman 找到了一个更好的解决方案:AbstractIndexedListIterator做我们想要的。唯一的缺点是这个类没有实现remove方法,并且封闭在Guava包中。所有这些都告诉我们,这些类确实很有用,但必须由用户在他的框架中实现。

JB Nizet 提出了另一种解决方案。除了在 getSize/GetItem(idx) 方法之上实现迭代器接口,我们可以返回从底层集合中检索到的一个。

于 2012-11-24T12:30:52.967 回答