【发布时间】:2023-03-21 10:17:01
【问题描述】:
我想知道为什么 Iterator.next() 会抛出 NoSuchElementException。通常,如果您使用迭代器,您会执行以下操作:
for(MyClass o: myFancyObject) {
o.doSomething();
}
将被编译为
Iterator it = myFancyObject.iterator();
while(it.hasNext()) {
MyClass o = (MyClass)(iterator.next());
o.doSomething();
}
但是为什么 next() 方法会抛出 NoSuchElementException 呢?
所以让我们在 next() 方法中调用 hasNext() 方法,如下所示:
public MyClass next() {
if (! hasNext())
throw new NoSuchElementException();
return mySecretDataModel.getElement(counter++);
}
但随后我检测到以下问题: hasNext() 方法将在每次迭代中被调用两次。首先它是从使用迭代器的方法调用的,然后是第二次由 next() 方法调用。这会花费不必要的计算时间。这是 Iterator 接口的作者的意图还是仅仅是设计疏忽?
【问题讨论】:
-
这个问题确实有点不清楚。 “但后来我检测到以下问题:hasNext() 方法将在每次迭代中调用两次。首先它从使用迭代器的方法调用,然后第二次由 next() 方法调用”这通常被认为是不好的练习,我想。这被称为副作用。由于您注意到的问题,这很糟糕。
-
Iterator
的 JavaDoc 说:“抛出:NoSuchElementException - 如果迭代没有更多元素” 那么,我是否需要遵守这个合同,或者仅仅实现 hasNext() 就足够了? -
我觉得没问题,只要方法是idempotent。
-
@MariusSpix: hasNext() 可能非常快,打破 Iterator 的合同以每小时获得几纳秒是一个坏主意。不要预先优化:它是万恶之源。并相信 JIT 可以将您经常使用的代码编译为快速的原生代码。
标签: java design-patterns interface iterator