对Java迭代器进行编程时,是否没有使其像peek()这样的函数有什么特殊原因,该函数会在不推进迭代器的情况下返回下一个元素?
答案 0 :(得分:14)
为什么标准的Java迭代器没有peek()?
因为peek()
不是Iterator设计模式的核心功能。
因为绝大多数迭代器用例都不需要它。强迫所有实现(包括无数的自定义/第三方类)实施不必要的方法将是一个坏主意。
因为peek()
方法会对惰性...源的迭代器的语义产生潜在影响。
由于实现peek()
在某些情况下会影响迭代器的效率(内存,CPU)。无论您是否实际使用它。
因为peek()
在某些晦涩的情况下会导致内存泄漏。
因为...吻。
但是最终,真正的原因是……因为他们早在2000年就以这种方式进行了设计。当设计辩论发生时,我们不在会议室 1 。
1-就其价值而言,似乎大多数 2 其他语言也对其标准迭代器API做出了相同的决定。 Rust似乎是个例外。参见https://doc.rust-lang.org/std/iter/struct.Peekable.html。
2-...基于使用Google搜索的高度不科学的“调查”。
如果您还需要提供peek()
的迭代器抽象,则可以扩展Iterator
接口并自己实现迭代器。确实,可以将通用的带迭代器的迭代器轻松实现为常规Iterator
的包装器。
或寻找第三方API /实施;例如Guava,Apache Commons等
答案 1 :(得分:1)
如果您确实需要使用peek()进行迭代,为什么不使用LinkedList
作为初始数据结构?它提供.peek()
和.pop()
来检索头部。
答案 2 :(得分:0)
以下示例使用peek
方法实现了迭代器。 remove
的实现留给读者。
import java.util.Iterator;
/**
* An Iterator with a peek method for just one value.
*/
public class PeekIterator<T> implements Iterator<T>
{
private Iterator<T> iterator;
public PeekIterator (Iterator<T> iterator) { this.iterator = iterator; }
private boolean peeked = false;
private T peeked_value = null;
public boolean hasNext () { return iterator.hasNext (); }
public T next ()
{
T value;
if (peeked) {
peeked = false;
value = peeked_value;
}
else
if (iterator.hasNext ())
value = iterator.next();
else
value = null;
return value;
}
public T peek ()
{
T value;
if (peeked)
value = peeked_value;
else {
peeked = true;
if (iterator.hasNext ())
peeked_value = iterator.next ();
else
peeked_value = null;
value = peeked_value;
}
return value;
}
}