Java 可索引集合的抽象迭代器

Java 可索引集合的抽象迭代器,java,indexing,iterator,abstract-class,Java,Indexing,Iterator,Abstract Class,我的框架充满了迭代器,比如 int n = col.getSize(); for (int i = 0 ; i != n; i++) { Type obj = col.get(i); 而且,我觉得每个在索引上迭代项的程序都有这样一段代码。与整洁的沙发相比,它感觉很难看 for (Type obj : col) { 转换到foreach需要使所有集合都可Iterable,这意味着在每个迭代器方法中创建一个新的迭代器。现在,我在每个集合声明中都有丑陋的代码,而不是它的使用位置。所以,我做得很

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

int n = col.getSize();
for (int i = 0 ; i != n; i++) {
  Type obj = col.get(i);
而且,我觉得每个在索引上迭代项的程序都有这样一段代码。与整洁的沙发相比,它感觉很难看

for (Type obj : col) {
转换到foreach需要使所有集合都可Iterable,这意味着在每个迭代器方法中创建一个新的迭代器。现在,我在每个集合声明中都有丑陋的代码,而不是它的使用位置。所以,我做得很好,我把难看的代码移到了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不提供这样的课程?每个人都需要它。我是不是忽略了它?

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

请看,抽象类的抽象行数与非抽象代码行数大致相同。现在,许多类可能想要实现可变迭代器,那么抽象类中几乎什么都没有了


此外,它永远不需要改变。如果抽象类允许您进行一次更改,例如修复一次bug,并同时修复多个类,那么抽象类尤其重要。然而,这段代码很简单,这个bug会是什么呢?例如,remove中的抛出几乎不会有bug——它永远不应该被执行。在多个迭代器之间共享它没有任何好处。

Tomasz Nurkiewicz指导我们使用番石榴的不可修改迭代器。但是,这里只定义了remove方法,而我们还需要索引迭代。这个提示让LouisWasserman找到了一个更好的解决方案:AbstractIndexedListIterator做我们想要的事情。唯一的缺点是该类没有实现remove方法,并且在Guava包中关闭。所有这些都告诉我们,这些类确实很有用,但必须由用户在其框架中实现


JB Nizet提出了另一个解决方案。我们可以返回从底层集合检索到的迭代器接口,而不是在getSize/GetItemidx方法之上实现迭代器接口

我想知道为什么Sun不提供这样的课程?每个人都需要它。我是不是忽略了它?您意识到所有标准集合都已经实现了Iterable,对吗?因此,它不是每个人都需要的;我从来都不需要它,因为我不编写自己的集合类,我使用预定义的集合类。你经历了所有这些重构只是为了摆脱basic for语句?您使用的集合类型是什么?总的来说:Java在不支持操作时有一个标准的异常类型:UnsupportedOperationException。实际上,此实现仅可用于列表,以及所有JDK列表,或者至少其中许多扩展了AbstractList,它定义了一个迭代器实现,当necessary@Mark彼得斯,我已经得到了答案,番石榴正是我想要的。为什么?你知道每个人都使用Iterable和standard集合吗?你如何计算?我只有两行抽象代码,重复使用了10行代码:initialize I,initialize size,I++,I==大小检查,抛出两个例外——所有东西每次都要复制粘贴。正当也许优秀的设计师认为复制粘贴是一种很好的编程实践,但糟糕的顾问告诉我,这节省了我大量的打字时间、产生错误的地方以及代码调整的方便性。我不计算IDE将动态生成的行数。所以我数了1行用于remove方法,1行用于size方法。等等。你说的这些行只是我不想在代码中看到的垃圾。IDE不会生成7条语句。你说的这些行只是我不想在代码中看到的垃圾。IDE不会生成7条语句。你说的这些行只是我不想在代码中看到的垃圾。IDE不会生成7条语句。你说的这些行只是我不想在代码中看到的垃圾。IDE将不会生成7条语句。这7条语句会将代码从处理器缓存中逐出,需要维护。出于后一个原因,程序员共享所有可能的代码,不管它有多简单。Haskell为4语句过程fx:map fxs引入了map函数。地雷模式更复杂。然而,您确实推广了垃圾编码并删除了注释。显然,Java类路径编写器不同,迭代器的代码共享没有任何用处。例如,热点可能是b e能够更好地内联独立迭代器,而不与其他迭代器共享代码。所以要么他们错过了分享代码的机会嗯。。它们确实有各种抽象集合类或者他们有理由不这样做。