2016-07-14 1 views
3

時間効率のよい方法で、多数の項目を書き込み、Java関数iterator.next()は要素をソースから削除できますか? (Java)の

public <T> void batchWrite(Iterable<T> source, int number) 

があります。

batchWrite()が書かれているConcurrentLinkedQueueにこのbatchWrite()を使用します。 batchWrite()には、キューから取得する項目を削除する必要があります。

私は戻された項目を削除しますそのイテレータを書く(およびIterableにそれをラップする)ことができます。

class IteratorThatRemovesReturnedValues<T> implements Iterator<T> { 
    Queue<T> queue; 
    IteratorThatRemovesReturnedValues(Queue<T> q) { queue = q; } 
    boolean hasNext() { return queue.peek() != null; } 
    T next() { return queue.poll(); } 
} 

質問です:はそれがコンセプトの乱用ではないでしょうか?

remove()の説明は言う:反復がこの(remove())メソッドを呼び出すこと以外の方法で進行中に基礎となるコレクションが変更された場合、イテレータの 動作は不定です。 これはいずれの方法でも読み取ることができます。Iteratorの特定の実装では、基本的な待ち時間のないキューが特定の方法で変更された場合の動作を定義することができます。

戻り値の要素を基になるキューから削除すると、イテレータのコントラクトと矛盾しますか?

(代替補助ArrayListpoll()にアイテムの量であり、そのリストにbatchWrite()を呼び出す。)

EDITこの問題の反対側:する反復子は、配管によってバックアップすることができます?

+0

IMO削除された項目を返すIteratorを実装せずに 'LinkedList'で同じことをすることができます... –

+0

はい、それは悪用されるでしょう。イテレータのnext()メソッドは削除されません。キューのイテレータを使用してremove()を呼び出すのはなぜですか? –

+1

完全に準拠したIteratorは、removeが呼び出されていないときに要素を削除すべきではないと言います。同じコレクションに対して2つのイテレータを作成し、両方を反復処理したいとします。 *ブーム*。 契約のあることは、特定の動作が期待できることです。あなたのイテレータが実際に 'IteratorThatRemovesReturnedValues'と呼ばれ、あなたが何を期待するのかを知るような振る舞いを文書化すれば、公式の意図した契約について心配することはありません。 – stuXnet

答えて

1

Iterator#remove()メソッドの(多くの)注意点を考慮していないと仮定すると、イテレータの動作は契約に従って単純です。特に、基本的な実装については何も言及していません。

サイドノート:これまでのところ、IteratorCollectionを超える反復に関連付けられていましたが、これは従来のEnumerationクラスの救済策にすぎません。多くのIteratorの実装は、ではなく、コレクションに関連するです。 (たとえば、Scannerなど)。今日、Iteratorは多くの場合、「利用可能なものがあるかどうかを問い合わせることのできる抽象的なソース」より多くはありません。

厳密に言えば、あなたの実装はすでにではなく、と契約しています。Iterator#next() methodのドキュメントは言う:

例外:

はNoSuchElementException - 繰り返し処理はそれ以上の要素

を持っていない場合、これはあなたのためのケースではありませんが。あなたの実装は単にここでnullを返します。もちろん、poll()コールをremove()へのコールに置き換えれば簡単に軽減できますが、便利にはNoSuchElementExceptionが返されますが、現在の目標と矛盾していると思います。

私は、next()メソッドの実装には、のになる副作用があると考えています。これらのイテレータ・インスタンスのうちの2つを作成すると、両方のイテレータ・インスタンスが契約に従って動作する可能性がありますが、両方の動作が予想どおりに異なる場合があります。

後者は、シングルスレッドを指しています。 2つのスレッドがこれらのイテレーターを独立して使用している場合、hasNext()next()への呼び出しの織り込みは競合状態を引き起こす可能性があります。 (2つのスレッドが1つのイテレータを使用している場合でも、すべてのイテレータの場合は、通常ステートフルであるため)。


一番下の行は次のとおりです。使用目的のいくつかの詳細は、特にイテレータがbatchWrite方法で使用されているかを正確の問題について(まだ明確ではない、とどのように複数のスレッドがここに対話することになっているが、 )これを実装するこの方法は、遅かれ早かれ破綻する可能性が高く、バグは検出して再現するのが難しいでしょう。ここでは別の実装を検討することをお勧めします。

関連する問題