java迭代器背后的概念是什么?

Bry*_*hen 4 java iterator concept

我正在研究java iterator接口,无法理解为什么它的设计是这样的.

为什么Java的迭代器使用hasNext,并next代替它们合并成一个方法?

这是java迭代器的典型用法

Iterator iter = //iterator from a list
while(iter.hasNext()){
    Object obj = iter.next();
    // do something to obj
}
Run Code Online (Sandbox Code Playgroud)

为什么不

Iterator iter = //iterator from a list
Object obj = null;
try {
    while(true){
        obj = iter.next();
        // do something to obj
    }
} catch (NoSuchElementException e) {}
Run Code Online (Sandbox Code Playgroud)

很明显,这种方法看起来很丑陋,但是如果next返回null到达end而不是抛出异常会发生什么?比代码可以简化为

Iterator iter = //iterator from a list
Object obj = null;
while((obj = iter.next()) != null){
    // do something to obj
}
Run Code Online (Sandbox Code Playgroud)

这就是Objective-C中NSEnumerator的工作原理

NSEnumerator *enumerator = // from an array
while (id obj = [enumerator nextObject]) {
    // do something to obj
}
Run Code Online (Sandbox Code Playgroud)

这增加了实现自定义的开销iterator.

这也使得java迭代器不是线程安全的.例如,ArrayList中包含一个元素.两个线程同时要求该列表使用相同的迭代器hasNext.两个线程都将看到,true并且它们将next在该迭代器上调用.因为只有一个元素,并且迭代器被要求两次,这肯定会导致异常或错误状态.

我知道有线程安全的迭代器,但我不确定它的实现,但我认为发生了很多阻塞,这使得它效率低下.

我认为问题是检查和更新不是原子地发生的,我无法理解为什么java设计这样的iterator界面.


更新

我看到null可以是一个值,所以我的方法是无效的.但是我上面提到的问题是否有任何可能的解决方法?

JB *_*zet 7

你的命题将使得null集合中的值不可能,因为它null用作"毒丸"来检测迭代的结束.

在非常罕见的情况下,两个线程共享一个迭代器,你只需要将它包装在一些自定义类中并同步对迭代器的访问,以使check-then-act操作成为原子.无论如何这都是必需的,因为即使迭代器只有一个方法,后台集合(在您的示例中为ArrayList)也不是线程安全的.