Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在Iterator.next()中使用NoSuchElementException?_Java_Design Patterns_Interface_Iterator - Fatal编程技术网

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

Java 如何在Iterator.next()中使用NoSuchElementException?,java,design-patterns,interface,iterator,Java,Design Patterns,Interface,Iterator,我想知道迭代器.next()为什么会抛出NoTouchElementException。通常,如果使用迭代器,您将执行以下操作: for(MyClass o: myFancyObject) { o.doSomething(); } 这将被编译为 Iterator it = myFancyObject.iterator(); while(it.hasNext()) { MyClass o = (MyClass)(iterator.next()); o.doSomethin

我想知道迭代器.next()为什么会抛出NoTouchElementException。通常,如果使用迭代器,您将执行以下操作:

for(MyClass o: myFancyObject) {
    o.doSomething();
}
这将被编译为

Iterator it = myFancyObject.iterator();
while(it.hasNext()) {
    MyClass o = (MyClass)(iterator.next());
    o.doSomething();
}
但是为什么next()方法抛出NoTouchElementException

让我们在next()方法中调用hasNext()方法,如下所示:

public MyClass next() {
    if (! hasNext())
        throw new NoSuchElementException();
    return mySecretDataModel.getElement(counter++);
}

但随后我发现了以下问题:hasNext()方法在每次迭代中将被调用两次。首先从使用迭代器的方法调用它,然后第二次由next()方法调用。这需要花费不必要的计算时间。这是迭代器接口的作者的意图还是设计疏忽?

迭代器出于几个原因可能抛出NoTouchElementException,但最明显的是调用方没有调用
hasNext()
或忽略结果。

您会这样编写吗

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

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

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

    return mySecretDataModel.getElement(counter++);
}

另一种选择是将迭代器状态存储在
hasNext()
期间计算的字段中,迭代器状态是一对
MyObject nextElement
boolean hasNext
,因此没有两次调用。第一个(尽管这里有所有其他答案)是我们应该从
next()
调用
hasNext()
,以避免代码重复。第二个是调用两次
hasNext()
是一个不必要的操作,计算成本很高

我们之所以从
next()
调用
hasNext()
,是因为。我们可以跳过此操作,让
next()
假设已经调用了
hasNext()
,并且我们的客户机知道他在做什么。但这可能会导致意外和不可预测的异常,例如
NullPointerException


因此,这里的答案是——这是一件好事,尽管它需要付出一些代价。

这个问题确实有点不清楚。“但随后我发现了以下问题:hasNext()方法在每次迭代中将被调用两次。首先,它是从使用迭代器的方法调用的,然后第二次由next()方法调用。”我认为,这通常被认为是一种不好的做法。这叫做副作用。正是由于您所注意到的问题,它才不好。迭代器的JavaDoc说:“Throws:NoSuchElementException-如果迭代没有更多的元素”,那么,我是否需要遵循这个契约,或者仅仅实现hasNext()就够了?我认为这很好,只要方法是这样。@MariusSpix:hasNext()可能非常快,打破迭代器的约定,每小时增加几纳秒是个坏主意。不要预先优化:这是万恶之源。并且信任JIT将您经常使用的代码编译为快速本机代码。。。所以仍然有一个双重检查。@MariusSpix在这种情况下,它不会检查不能执行两次的任何内容,性能成本是概念性的,因为分支预测将跳过条件为false的常见情况。