JavaのIteratorとListIteratorが要素間を指すのはなぜですか?


9

ListIteratorJavadocは次のように述べています。

AにListIteratorは現在の要素がありません。カーソル位置は常に、への呼び出しによって返されるprevious()要素とへの呼び出しによって返される要素の間にありますnext()

Java ListIteratorが現在の要素ではなく要素間を指すように実装されたのはなぜですか?繰り返し呼び出す必要があるとき、これはクライアントコードが読みにくくなりますようだgetNext()getPrevious()私は選択のための正当な理由がなければならないと仮定して、。

注意点として、私はちょうど書いたpeekable-のArrayListと呼ばれる小さなライブラリ拡張ArrayListIteratorおよびListIteratorその提供peekAtNext()peekAtPrevious()同じように実装する方法を:

  @Override public synchronized T peekAtNext() {
     T t = next();
     previous();
     return t;
  }


ケビンさん、ありがとう!私
glenviewjeff 2012年

回答:


12

私が知る限り、その理由はあなたが引用しなかったjavadocの部分にあります(私の強調は下にあります):

プログラマがリストをいずれかの方向にトラバースし、反復中にリストを変更できるようにするリストのイテレータ...

ご覧のとおり、意図された目的は、リストの変更中に使用を許可することです。可能な変更には明らかに要素の削除が含まれます。

current()イテレータの要素を削除するとどうなるかを考えてみてください-イテレータが現在の要素の概念を持っていると仮定すると?このコンテキストでは、現在の要素の概念なしでそれを実装する方法は、私にとって非常に理にかなっています。その方法では、イテレータは要素の削除について心配する必要がないからです。


javadocでは、スレッドを安全にするためにインターフェース実装を必要としないことに注意することが重要です。

  • そのため、異なるスレッドから行われた変更の正しい処理を期待すべきではありません。そのため、実装は、JSR 133によるJavaメモリモデルで指定されているアクセスの同期、可視性の保証などの追加手段を提供する必要があります。

ListIteratorで可能なことは、反復時に同じスレッドから行われた変更を処理することです。すべてのイテレータがそのようになっているわけではありません。ConcurrentModificationExceptionjavadocsは特にこれについて警告します。

...この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。単一のスレッドがオブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行した場合、オブジェクトはこの例外をスローする可能性があります。たとえば、スレッドがコレクションを直接変更しているときに、コレクションをフェイルファストイテレータで繰り返している場合、イテレータはこの例外をスローします...


1
また、別のinsertBeforeand は必要ありませんが、insertAfterほど大きな問題ではありませんremove
カールビーレフェルト

1
それで、現在の要素を同時に削除してアクセスできるという問題はありますか?これは、同時呼び出しと同等の問題ではないでしょうnext()か? remove()のようsynchronizedになりgetCurrent()ます。何か不足していますか?
glenviewjeff 2012

@glenviewjeffそれは非常に良い観察です。また、CMEがそこでどのように処理されるのかについても疑問に思います。変更を許可するという非常に明確な意図は、そのような懸念を引き起こします。もっと深く掘り下げる必要があると思います。99.99%は、スレッドセーフではないことを確信しています。おそらく、同じスレッドから実行された同時MODしか処理できない(すべてのイテレータがそれを実行できるわけではありません)
gnat

興味があれば、私の編集を見てください。これを実現するための拡張機能を実装してパッケージ化しましたArrayList
glenviewjeff

@glenviewjeff面白い。あなたの実装では、next()とprevious()も同期されていますか?そうでない場合、他のスレッドが予期しない移動をcurrent()の真ん中に「ドリル」して、クライアントが期待するように動作しない可能性があるためです... add()のようなメソッドもおそらく同期が必要です
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.