改进了集合迭代器

时间:2008-10-10 17:44:21

标签: java collections iterator decorator

就个人而言,我发现java.util.Iterator提供的功能范围相当可怜。至少,我希望有以下方法:

  • peek()返回下一个元素而不移动迭代器前进
  • previous()返回前一个元素

虽然还有许多其他可能性,例如first()和last()。

有谁知道这样的第三方迭代器是否存在?它可能需要作为java.util.Iterator的装饰器实现,以便它可以使用现有的Java集合。理想情况下,它应该是“泛型意识”。

提前致谢, 唐

11 个答案:

答案 0 :(得分:10)

只需使用previous()即可轻松获得java.util.ListIterator

通过执行

可以轻松实现这一点
public <T> T peek(ListIterator<T> iter) throws NoSuchElementException {
    T obj = iter.next();
    iter.previous();
    return obj;
}

不幸的是,将它作为实用程序方法会更容易,因为每个集合类都实现了自己的迭代器。要做一个包装器来获取某个接口(例如MyListIterator)上的每个集合的peek方法,这将是相当多的工作。

答案 1 :(得分:8)

我认为这些没有实现的原因是因为它们对某些集合来说非常重要,并且会产生很大的性能影响。我认为你可以非常简单地为你关心的收藏品做这项工作。

我也不喜欢Java迭代器无法在不移动的情况下获取当前值(因此您无法轻松编写基于该值的分支代码,只需传递迭代器 - 您必须通过你现在拥有的价值)。

答案 2 :(得分:8)

答案 3 :(得分:4)

通用运营商没有实现这些功能有一个很好的理由:它们不适用于所有容器。典型的示例是表示一些外部数据输入的容器,如看作流的文件。每次你读取一个值消耗它并向前移动指针,如果你想要或不想。如果将这些约束强加给泛型迭代器,那么就会失去迭代器的通用性。

如果您想要previous方法,请按照建议使用ListIterator<>,然后将其限制为容器表现为列表。

答案 4 :(得分:3)

我要看的一件事是clojure中的Seq实现

http://clojure.org/sequences

基类的实现是用Java完成的,并且可以使用完整的源代码。 Seqs是java迭代器上的装饰器(采用并实现java迭代器接口) - 但它们也提供了自己的接口,可能更符合您的需求 - 或者至少是一个起点。

答案 5 :(得分:1)

正如ykaganovich建议的那样,您可能想查看google-collections内容。对于你想要的一些东西肯定有一些支持,比如peeking。此外,正如其他人所提到的,从可能性或性能角度来看,为所有集合实现所有这些内容可能是危险的。

答案 6 :(得分:1)

public class Iterazor<T> {
  private Iterator<T> it;
  public T top;
  public Iterazor(Collection<T> co) {
    this.it = co.iterator(); 
    top = it.hasNext()? it.next(): null; 
  }
  public void advance() { 
    top = it.hasNext()? it.next(): null; 
  }
}

// usage

for(Iterazor<MyObject> iz = new Iterazor<MyObject>(MyCollection); 
    iz.top!=null; iz.advance())
  iz.top.doStuff();
}

答案 7 :(得分:1)

我看到有人链接到Google Collections,但没有人提到您要查找的方法名为Iterators.peekingIterator()。

尽管如此,最好还是使用ListIterator。

答案 8 :(得分:0)

我还没遇到过我需要偷看的问题(); Iterator对我来说工作得很好。我很好奇你是如何使用迭代器的,你觉得你需要这个附加功能。

答案 9 :(得分:0)

听起来你最好不要使用Stack。

答案 10 :(得分:0)

编写Java集合是为了提供一组最有用的功能。对于任何实现Java的人来说,具有的代码,这是一种非常好的方法。使用可能有用的功能来扩展接口可能会导致代码量的大幅增加,只有少数人注意到这些改进。如果peek()和previous()是标准迭代器的一部分,那意味着每个人都在编写一种新的Collection 必须来实现它,无论它是否合理。

迭代器也可用于处理物理无法倒退的事物,使得peek()和previous()都不可能。