4

私はJavaiteratorインターフェースについて調査していますが、なぜそのように設計されているのか理解できません。

java イテレータを使用hasNextして、next代わりにそれらを 1 つのメソッドにマージするのはなぜですか?

これはJavaイテレータの典型的な使用法です

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

なぜだめですか

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

このアプローチが見栄えが悪いことは明らかですがnext、最後に到達したときに null を返す代わりに例外をスローするとどうなるでしょうか? コードを単純化できるよりも

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

これがObjective-CのNSEnumeratorの仕組みです

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

これにより、カスタム実装のオーバーヘッドが増加しますiterator

これにより、Java イテレータもスレッドセーフではなくなります。たとえば、ArrayList には 1 つの要素があります。2 つのスレッドが両方とも、そのリストの同じ反復子を同時に要求しますhasNext。両方のスレッドが認識し、そのイテレータでtrue呼び出します。next要素が 1 つしかなく、反復子が 2 回要求されているため、間違いなく例外またはエラー状態になります。

スレッドセーフなイテレータがあることは知っていますが、それが実装されているかどうかはわかりませんが、多くのブロッキングが発生して非効率になっていると思います。

問題は、チェックと更新がアトミックに行われないことだと思います。なぜJavaiteratorがそのようなインターフェースを設計したのか理解できません。


アップデート

null が値になる可能性があるため、私のアプローチは無効です。しかし、上記の問題に対する回避策はありますか?

4

3 に答える 3

7

あなたの命題は、反復の終わりを検出するための「毒薬」としてnull使用されるため、コレクションに値を持つことを不可能にします。null

非常にまれなケースですが、2 つのスレッドが反復子を共有している場合は、それをカスタム クラス内にラップし、反復子へのアクセスを同期して、check-then-act 操作をアトミックにする必要があります。イテレータにメソッドが1つしかない場合でも、バッキングコレクション(例ではArrayList)はスレッドセーフではないため、とにかくこれが必要です。

于 2012-03-02T09:11:18.547 に答える
4

最初の提案は、最終的に発生することがわかっている状態の例外をスローしてキャッチすることに依存しているため、設計が不十分です。例外はかなりコストがかかり、通常は発生しない「例外的な」状況のみを対象としています。

Iterable2番目の提案では、 s が null 要素を持つ可能性があることを考慮していません。

スレッド セーフティ ビットに関しては、はい、標準Iteratorはスレッド セーフではない傾向があり、オーバーヘッドを追加したカスタム実装が必要になります。これは、ほとんどの Java 構造に当てはまります。JB Nizet が指摘しているように、Iterable構造がスレッドセーフになる前に、構造がスレッドセーフにIteratorなることが重要です。

于 2012-03-02T09:13:57.337 に答える
2

ソースコードの明確さを向上させるには、(文字列のコレクションを使用した例)を使用します。

Iterable<String> values = ... // typically a Collection (List, Set...)

for (String value : values) {
    // do something with the value
}

null制限のあるコレクション、例外を伴うループ制御(これはひどい形式です)、およびスレッドセーフに関する以前の回答に同意します。

あなたの提案の中で、特にコードに「nullなし」のポリシーがある場合は、コレクションをnullで制限することは賢明ではありません。ただし、これは非常に単調なJava(edit:およびIteratorインターフェースのコントラクトを破る)であるため、コードの将来のメンテナーを混乱させる可能性があります(edit:および場合によっては微妙なバグや予期しないバグを引き起こす可能性があります)。

于 2012-03-02T09:34:20.987 に答える