36

Java Collections Framework がリンクされたリストにデータ構造を実装する方法について学びました。私が理解していることからIterators、リストなどのデータ構造内のアイテムをトラバースする方法があります。このインターフェイスが使用される理由 メソッドがhasNext()next()ありremove()、データ構造の実装自体に直接コーディングされていないのはなぜですか?

Java Web サイトから:リンク テキスト

パブリック インターフェイス Iterator<E>

コレクションに対する反復子。イテレータは、Java コレクション フレームワークで Enumeration に取って代わります。イテレータは、次の 2 つの点で列挙型とは異なります。

  • イテレータを使用すると、呼び出し元は、明確に定義されたセマンティクスを使用して、反復中に基になるコレクションから要素を削除できます。
  • メソッド名が改善されました。
このインターフェースは、Java Collections Framework のメンバーです。

グーグルで調べてみましたが、明確な答えが見つからないようです。Sunがそれらを使用することを選択した理由を誰かが明らかにすることができますか? デザインが良いからでしょうか?セキュリティ強化?グッド OO プラクティス?

どんな助けでも大歓迎です。ありがとう。

4

16 に答える 16

18

なぜこのインターフェースが使われるのですか?

Collectionこれは、クライアントプログラマーがあらゆる種類のコレクションを反復処理できるようにする基本的な操作をサポートしているためです(注:ある意味では必ずしもそうではありませんObject)。

メソッドが...データ構造の実装自体に直接コーディングされていないのはなぜですか?

それらは、プライベートとしてマークされているだけなので、それらに手を伸ばしたり、それらをいじったりすることはできません。すなわち:

  • Iterator反復する実際のオブジェクトを変更することなく、標準のオブジェクトでは実行されないことを実行するように実装またはサブクラス化できます。
  • トラバースできるオブジェクトは、トラバーサルメソッド、特に高度に特殊化されたメソッドでインターフェイスを乱雑にする必要はありません。
  • あなたはあなたがIterators望むどんなに多くのクライアントにも配ることができます、そして各クライアントは彼ら自身の時間に彼ら自身の速度で横断するかもしれません。
  • 特にjava.utilパッケージのJavaIteratorsは、それらをバックアップするストレージがまだIteratorアウトになっている間に変更された場合、例外をスローします。Iteratorこの例外により、が無効なオブジェクトを返す可能性があることがわかります。

単純なプログラムの場合、これはおそらく価値がないように思われます。しかし、それらを便利にするような複雑さはすぐに思い浮かびます。

于 2008-09-18T05:06:50.500 に答える
6

「メソッド hasNext()、next()、remove() がデータ構造の実装自体に直接コーディングされていないのはなぜですか?」

Java Collections フレームワークは、コレクション自体に外部化されたものとして Iterator インターフェースを定義することを選択します。通常、すべての Java コレクションはIterableインターフェースを実装するため、Java プログラムは呼び出しiteratorて独自の反復子を作成し、ループで使用できるようにします。他の人が指摘したように、Java 5 では、for-each ループを使用して反復子を直接使用できます。

イテレータをそのコレクションに外部化すると、クライアントはコレクションを反復する方法を制御できます。これが役立つと考えられる使用例の 1 つは、インデックス化するインターネット上のすべての Web ページなど、無制限のコレクションがある場合です。

古典的な GoF の本では、内部イテレータと外部イテレータの対比が明確に説明されています。

基本的な問題は、反復を制御する当事者、反復子、または反復子を使用するクライアントを決定することです。クライアントが反復を制御する場合、反復子は外部反復子と呼ばれ、反復子が制御する場合、反復子は内部反復子と呼ばれます。外部反復子を使用するクライアントは、走査を進め、反復子から次の要素を明示的に要求する必要があります。対照的に、クライアントは実行する操作を内部反復子に渡し、反復子はその操作をすべての要素に適用します ....

外部反復子は、内部反復子よりも柔軟です。たとえば、外部反復子を使用して 2 つのコレクションの等価性を比較するのは簡単ですが、内部反復子では事実上不可能です。

内部反復子がどのように機能するかの例については、Ruby のEnumerableAPI を参照してください。これには、 などの内部反復メソッドがありますeach。Ruby では、コードのブロック (つまり、クロージャ) を内部反復子に渡して、コレクションが独自の反復を処理できるようにするという考え方です。

于 2008-09-18T05:22:18.950 に答える
5

コレクションをポインターから離しておくことが重要です。イテレータはコレクション内の特定の場所を指しているため、コレクションの不可欠な部分ではありません。このようにして、たとえば、同じコレクションに対して複数の反復子を使用できます。

この分離の欠点は、イテレーターが反復対象のコレクションに加えられた変更を認識しないことです。そのため、コレクションの構造を変更して、イテレータが「苦情」なしで作業を継続することを期待することはできません。

于 2008-09-18T09:33:25.133 に答える
3

インタレータの複数のインスタンスを同時に使用できます。基になるデータのローカルカーソルとしてそれらにアプローチします。

ところで:具体的な実装よりもインターフェースを優先すると、結合が緩みます

イテレータのデザインパターンを探してください。http://en.wikipedia.org/wiki/Iterator

于 2008-09-18T05:32:46.413 に答える
3

インターフェイスを使用するIteratorと、そのメソッドを実装するすべてのクラスがイテレータとして機能できるようになります。implementsJavaのインターフェースの概念は、ある意味で、インターフェースが必要とする方法で動作するように、インターフェースのクラスに特定の機能を提供するという契約上の義務を負うことです。有効なクラスであるためには契約上の義務を果たさなければならないので、クラスをimplementsインターフェースとして見る他のクラスは、クラスがそれらの特定の機能を持っていることを知って安心します。

この例では、クラス自体にメソッド( hasNext(), next(), remove())を実装するのではなく、クラスがそれをインターフェースとして宣言するため、他の人は、がイテレーターとして使用できることを知っています。次に、クラスはインターフェイス(など)からメソッドを実装するため、イテレータのように機能できます。LinkedListLinkedListimplementsIteratorLinkedListLinkedListIteratorhasNext()

言い換えれば、インターフェースの実装は、特定のクラスがそれが主張するものであるために必要なものを持っていることを他の人に知らせるためのオブジェクト指向プログラミングの概念です。

この概念は、インターフェースを実装するクラスによって実装されなければならないメソッドを持つことによって実施されます。これにより、インターフェイスを実装するクラスを使用したい他のクラスがIterator、イテレータが持つべきメソッド(など)を実際に持つようになりhasNext()ます。

また、Javaには多重継承がないため、インターフェイスを使用してその機能をエミュレートできることに注意してください。複数のインターフェースを実装することにより、一部の機能を継承するサブクラスであるクラスを持つことができますが、インターフェースを実装することによって別の機能を「継承」することもできます。一例として、逆の順序で反復できるというLinkedListクラスのサブクラスが必要な場合は、というインターフェイスを作成して、メソッドを提供するように強制することができます。はすでに実装されているため、新しいリバーシブルリストはとインターフェイスの両方を実装しているはずです。ReversibleLinkedListReverseIteratorprevious()LinkedListIteratorIteratorReverseIterator

インターフェイスの詳細については、「インターフェイスとは」を参照してください。SunのJavaチュートリアルから。

于 2008-09-18T04:39:34.763 に答える
2

データ構造ではないものを繰り返し処理している可能性があるためです。サーバーから結果を取得するネットワーク アプリケーションがあるとします。これらの結果の周りに Iterator ラッパーを返し、Iterator オブジェクトを受け入れる任意の標準コードを通じてストリーミングできます。

これは、優れた MVC 設計の重要な部分と考えてください。データは、何らかの形でモデル (つまりデータ構造) からビューに取得する必要があります。Iterator を仲介者として使用すると、Model の実装が公開されないことが保証されます。LinkedList をメモリに保持したり、復号化アルゴリズムから情報を引き出したり、JDBC 呼び出しをラップしたりすることができます。ビューは Iterator インターフェースのみを気にするため、ビューには関係ありません。

于 2008-09-18T04:12:46.887 に答える
1

最終的に、Iterator は多数のデータ構造に適用可能なコントロールの抽象化をキャプチャするためです。圏論に精通している場合は、次の論文に圧倒されるかもしれません: The Essence of the Iterator Pattern .

于 2008-09-18T05:21:39.340 に答える
1

私はそれがOOの良い練習だと思います。あらゆる種類の反復子を処理するコードを持つことができ、独自のデータ構造を作成したり、反復子インターフェイスを実装する単なるジェネリック クラスを作成したりすることさえできます。その背後にある実装の種類について心配する必要はありません。

于 2008-09-18T04:11:49.993 に答える
1

ご存知ない場合は、M2C だけです。for -eachループで十分な状況では、反復子インターフェイスを直接使用することを避けることができます。

于 2008-09-18T04:14:15.633 に答える
1

イテレータを使用することの長所と短所について議論している興味深い論文:

http://www.sei.cmu.edu/pacc/CBSE5/Sridhar-cbse5-final.pdf

于 2008-09-18T04:10:12.040 に答える
0

イテレータは、あらゆる種類のコレクションに対して使用できます。これらを使用すると、基礎となる実装に関係なく、アイテムのコレクションに対してアルゴリズムを定義できます。これは、リスト、セット、文字列、ファイル、配列などを処理できることを意味します。

今から10年後、リストの実装をより良い実装に変更することができ、アルゴリズムはそれに対してシームレスに実行されます。

于 2008-09-18T04:34:31.700 に答える
0

イテレータは、Java でコレクションを扱う場合に便利です。

コレクション、配列、またはリストを反復処理するには、For-Eachループ (Java1.5) を使用します。

于 2008-09-18T05:21:04.523 に答える
0

イテレータは、アイテムのコレクションを処理する一般的な方法を追加するだけです。優れた機能の 1 つは i.remove() で、繰り返しているリストから要素を削除できます。通常、リストからアイテムを削除しようとすると、奇妙な効果が発生したり、例外が発生したりします。

インターフェイスは、それを実装するすべてのものの契約のようなものです。あなたは基本的に言っています..イテレータを実装するものはすべて、これらのメソッドが同じように動作することが保証されています。コード内で処理することだけが重要な場合は、イテレータ型を渡すために使用することもできます。(リストのタイプは気にしないかもしれません..単にイテレータを渡したいだけです)これらすべてのメソッドをコレクションに個別に配置できますが、それらが同じように動作すること、またはそれらが同じ名前を持っていることさえ保証していません。署名。

于 2008-09-18T04:12:41.690 に答える
0

イテレータは、Java で使用できる多くの設計パターンの 1 つです。デザイン パターンは、便利なビルディング ブロック、スタイル、コード/構造の使用法と考えることができます。

Iterator デザイン パターンの詳細については、Iterator や他の多くのデザイン パターンについて説明しているこの Web サイトを参照してください。Iterator のサイトからのスニペットを次に示します: http://www.patterndepot.com/put/8/Behavioral.html

Iterator は、最も単純で最も頻繁に使用される設計パターンの 1 つです。Iterator パターンを使用すると、データの内部表現の詳細を知らなくても、標準インターフェイスを使用してデータのリストまたはコレクションを移動できます。さらに、特別な処理を実行し、データ コレクションの指定された要素のみを返す特別な反復子を定義することもできます。

于 2008-09-18T04:23:16.563 に答える
0

最初の箇条書きにより、マルチスレッド (または失敗した場合はシングル スレッド) アプリケーションが同時実行違反のためにコレクションをロックする必要がないように思えます。たとえば.NETでは、コレクション(またはリストまたは任意のIEnumerable)を同時に列挙および変更することはできません。IEnumerableからロックまたは継承し、メソッドをオーバーライドする必要があります(例外が発生します)。

于 2008-09-18T04:06:59.117 に答える
0

java.util.Iterator インターフェイスは、Java Collections Framework で使用され、コレクションを反復しながらコレクションを変更できるようにします。コレクション全体をきれいに反復したいだけの場合は、代わりに for-each を使用しますが、イテレーターの利点は、オプションの remove() 操作を利用できる機能です。 () および set() 操作も。これらのインターフェースはどちらも、コレクションを繰り返し処理し、同時に構造的に変更することを可能にします。コレクションを for-each で反復処理中に変更しようとすると、ConcurrentModificationException がスローされます。これは通常、コレクションが予期せず変更されるためです。

ArrayList クラスを見てください。

内部には Itr と ListItr という 2 つのプライベート クラス (内部クラス) があります。

これらは、それぞれ Iterator および ListIterator インターフェースを実装します。

public class ArrayList..... { //エンクロージング クラス

  private class Itr implements Iterator<E> {

        public E next() {
            return ArrayList.this.get(index++); //rough, not exact
        }

        //we have to use ArrayList.this.get() so the compiler will
        //know that we are referring to the methods in the 
        //enclosing ArrayList class

        public void remove() {
            ArrayList.this.remove(prevIndex);
        }

        //checks for...co mod of the list
        final void checkForComodification() {  //ListItr gets this method as well
             if (ArrayList.this.modCount != expectedModCount) { 
                 throw new ConcurrentModificationException();
             }
        }
  }

  private class ListItr extends Itr implements ListIterator<E> {
         //methods inherted....
        public void add(E e) {
            ArrayList.this.add(cursor, e);
        }

        public void set(E e) {
            ArrayList.this.set(cursor, e);
        }
  }

}

メソッド iterator() および listIterator() を呼び出すと、プライベート クラス Itr または ListItr の新しいインスタンスが返されます。これらの内部クラスは、それを囲む ArrayList クラスの「内部」にあるため、ConcurrentModificationException をトリガーすることなく、ArrayList を自由に変更できます。 ArrayList クラスの set() add() または remove() メソッドを使用して同時に (同時に) リストを変更しない限り。

于 2015-10-21T03:51:19.007 に答える