如何在Iterator.next()中使用NoSuchElementException?

时间:2013-11-27 20:43:43

标签: java design-patterns interface iterator

我想知道为什么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界面的作者的设计监督?

4 个答案:

答案 0 :(得分:1)

iterator可能由于某些原因而抛出NoSuchElementException,但最明显的是调用者没有调用hasNext()或忽略结果。

答案 1 :(得分:0)

你会这样写的

public MyClass next() {
    if (counter >= mySecretDataModel.getSize())
        throw new NoSuchElementException();
    return mySecretDataModel.getElement(counter++);
}

答案 2 :(得分:0)

我认为不需要致电hasNext(),更好的方法是:

public MyClass next() {
    if (counter >= mySecretDataModel.size())
        throw new NoSuchElementException();

    return mySecretDataModel.getElement(counter++);
}

另一个选择是你在MyObject nextElement期间计算的字段中存储你的迭代器状态,它是一对boolean hasNexthasNext(),因此没有两次调用。

答案 3 :(得分:0)

你在两个陈述中都是完全正确的。第一个(尽管这里有所有其他答案)是我们应该从hasNext()调用next(),以避免代码重复。第二个是调用hasNext()两次是不必要的操作,计算成本。

由于defensive,我们正在hasNext()next()进行此次调用。我们可以跳过此操作,让next()假设hasNext()已经被调用,我们的客户知道他在做什么。但这可能会导致意外和不可预测的异常,例如NullPointerException

所以,这里的答案是 - defensive programming是好事,即使它花费了一些东西。