就个人而言,我发现 java.util.Iterator 提供的功能范围相当可悲。至少,我希望有以下方法:
- peek() 返回下一个元素而不向前移动迭代器
- previous() 返回前一个元素
尽管还有很多其他的可能性,例如 first() 和 last()。
有谁知道这样的第 3 方迭代器是否存在?它可能需要实现为 java.util.Iterator 的装饰器,以便它可以与现有的 java 集合一起使用。理想情况下,它应该是“泛型意识”。
在此先感谢,唐
就个人而言,我发现 java.util.Iterator 提供的功能范围相当可悲。至少,我希望有以下方法:
尽管还有很多其他的可能性,例如 first() 和 last()。
有谁知道这样的第 3 方迭代器是否存在?它可能需要实现为 java.util.Iterator 的装饰器,以便它可以与现有的 java 集合一起使用。理想情况下,它应该是“泛型意识”。
在此先感谢,唐
只需previous()
使用java.util.ListIterator
.
窥视这一点很容易通过执行
public <T> T peek(ListIterator<T> iter) throws NoSuchElementException {
T obj = iter.next();
iter.previous();
return obj;
}
不幸的是,将它作为一种实用方法会更容易,因为每个集合类都实现了自己的迭代器。做一个包装器以在某些接口上的每个集合上获取一个 peek 方法,例如MyListIterator
将是相当多的工作。
我认为这些没有实现的原因是因为它们对于某些集合来说并不重要,并且会对性能产生很大的影响。我认为为您关心的收藏品制作这项工作对您来说非常简单。
我也不喜欢 Java 迭代器无法在不移动它的情况下获取当前值(因此你不能轻易地编写基于值分支的代码,只需传递迭代器——你必须传递你的值现在也有)。
通用运算符没有实现这些特性是有一个很好的理由:它们并不适用于所有容器。典型的例子是一个代表一些外部数据输入的容器,比如一个被视为流的文件。每次您读取一个值时,您都会使用它并将指针向前移动,无论您是否愿意。如果你对泛型迭代器施加这些约束,那么你就会失去迭代器的泛型性。
如果您想要一种previous
方法,如建议的那样,请使用ListIterator<>
,然后将其限制为容器表现为列表。
我要看的一件事是 clojure 中的 Seq 实现
基类的实现是用 Java 实现的,并且可以使用完整的源代码。Seq 是 Java 迭代器上的装饰器(采用并实现 Java 迭代器接口)——但它们也提供自己的接口,这可能是你想要的更多——或者至少是一个起点。
我看到有人链接到Google Collections,但是没有人提到您要查找的方法称为Iterators.peekingIterator()。
不过,最好只使用 ListIterator。
正如 ykaganovich 建议的那样,您可能想查看google-collections 的东西。你想要的一些东西肯定有一些支持,比如偷看。此外,正如其他一些人所提到的,从可能性或性能的角度来看,为所有集合实现所有这些东西可能是危险的。
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();
}
我从来没有遇到过需要 peek(); 的问题。迭代器对我来说工作得很好。我很好奇你是如何使用你觉得你需要这个附加功能的迭代器的。
听起来你最好使用堆栈。
编写 Java 集合是为了提供一组最小的有用功能。对于任何实现 Java 的人都必须实现的代码,这是一种非常好的方法。使用可能有用的功能使界面膨胀可能会导致代码量大幅增加,而只有少数人注意到了改进。如果 peek() 和 previous() 是标准迭代器的一部分,这意味着每个编写新类型 Collection 的人都必须实现它,无论它是否合理。
迭代器还被设计用于处理物理上不能倒退的事情,这使得 peek() 和 previous() 都不可能。