我的框架充满了像
这样的迭代器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)。唯一的问题是性能penaly:我必须在循环中进行两次大小检查,首先是hasNext,另一个是next()。我想知道为什么Sun不提供这样的课程?每个人都需要它。我只是忽略了它吗?
答案 0 :(得分:1)
在抽象类中共享的代码很少,因此抽象几乎没有带来任何好处。我认为在每个集合中从头开始实现这样的迭代器同样容易。在许多情况下,hasNext
可能更直接地实现,例如。
请注意,您的抽象类具有与非抽象代码行一样多的抽象行。现在,许多类可能想要实现可变迭代器,然后在抽象类中几乎没有任何东西。
另外,永远不需要改变。如果允许您进行一次错误修改等更改并同时修复多个类,则抽象类特别好。但是,这段代码很简单,这个bug会是什么?例如,“删除”中的“抛出”几乎没有错误 - 它永远不应该被执行。在多个迭代器中共享它没有任何好处。
答案 1 :(得分:0)
Tomasz Nurkiewicz将我们带到了番石榴的UnmodifiableIterator
。但是,这里只定义了remove方法,而我们也想要索引迭代。这个提示让LouisWasserman找到了更好的解决方案:AbstractIndexedListIterator
做了我们想要的。唯一的缺点是这个类没有实现remove方法,而是在Guava包中关闭。所有这些告诉我们这些类非常有用,但必须由用户在他的框架中实现。
JB Nizet提出了另一种解决方案。我们可以返回从底层集合中重新获取的一个迭代器接口,而不是在getSize / GetItem(idx)方法之上实现迭代器接口。