Javaコレクションフレームワークがリンクリストのデータ構造を実装する方法について学びました。私が理解していることから、Iterators
は次のようなデータ構造のアイテムをトラバースする方法です。リスト。なぜこのインターフェースが使用されるのですか?メソッドhasNext()
、next()
およびremove()
がデータ構造実装自体に直接コーディングされていないのはなぜですか?
Javaウェブサイトから: リンクテキスト
パブリックインターフェイスIterator <E>
コレクションに対するイテレータ。イテレータは、Javaコレクションフレームワークの列挙の代わりになります。イテレータは、次の2つの点で列挙とは異なります。
このインターフェースはJavaコレクションフレームワークのメンバーです。
- イテレータを使用すると、呼び出し元は、明確に定義されたセマンティクスを使用して、反復中に基になるコレクションから要素を削除できます。
- メソッド名が改善されました。
グーグルしてみましたが、明確な答えが見つからないようです。誰かがSunがそれらを使用することを選んだ理由に光を当てることができますか?デザインが良いからですか?セキュリティの強化?良いOO練習?
どんな助けでも大歓迎です。ありがとう。
なぜこのインターフェースが使われるのですか?
これは、クライアントプログラマーがあらゆる種類のコレクションを反復処理できるようにする基本的な操作をサポートしているためです(注:必ずしもCollection
の意味でObject
である必要はありません)。
メソッドが...データ構造の実装自体に直接コーディングされていないのはなぜですか?
それらは、プライベートとしてマークされているだけなので、それらに手を伸ばしてそれらをいじることはできません。すなわち:
Iterator
を実装またはサブクラス化して、反復する実際のオブジェクトを変更することなく、標準のオブジェクトでは実行できないことを実行できます。Iterators
を好きなだけクライアントに配ることができ、各クライアントは自分の時間に自分の速度で移動できます。Iterators
は、Iterator
がまだ出力されているときに、それらをバックアップするストレージが変更された場合に例外をスローします。この例外により、Iterator
が無効なオブジェクトを返している可能性があることがわかります。単純なプログラムの場合、これはおそらく価値がないようです。しかし、それらを便利にするような複雑さはすぐに思い浮かびます。
「メソッドhasNext()、next()、remove()がデータ構造の実装自体に直接コーディングされていないのはなぜですか?」と質問します。
Javaコレクションフレームワークは、コレクション自体に外部化されたものとしてIteratorインターフェースを定義することを選択します。通常、すべてのJavaコレクションはIterable
インターフェイスを実装しているため、Javaプログラムはiterator
を呼び出して、使用できるように独自のイテレータを作成します。ループで。他の人が指摘しているように、Java 5を使用すると、for-eachループを使用してイテレータを直接使用できます。
イテレータをコレクションに外部化することで、クライアントはコレクションを反復処理する方法を制御できます。これが役立つと思うユースケースの1つは、インデックスを作成するインターネット上のすべてのWebページなど、無制限のコレクションがある場合です。
古典的なGoFの本では、内部イテレータと外部イテレータの対比が非常に明確に説明されています。
基本的な問題は、イテレータを制御するパーティ、イテレータ、またはイテレータを使用するクライアントを決定することです。クライアントが反復を制御する場合、イテレーターは外部イテレーターと呼ばれ、イテレーターがそれを制御する場合、イテレーターは内部イテレーターです。外部イテレータを使用するクライアントは、トラバーサルを進めて、イテレータに次の要素を明示的に要求する必要があります。対照的に、クライアントは内部イテレータに実行する操作を渡し、イテレータはその操作をすべての要素に適用します..。
外部イテレータは、内部イテレータよりも柔軟性があります。たとえば、2つのコレクションが等しいかどうかを外部イテレータと比較するのは簡単ですが、内部イテレータでは事実上不可能です...一方、内部イテレータは反復ロジックを定義するため、使いやすくなっています。
内部イテレータがどのように機能するかの例については、RubyのEnumerable
APIを参照してください。これには、each
などの内部反復メソッドがあります。 Rubyでは、コードのブロック(つまりクロージャ)を内部イテレータに渡して、コレクションがそれ自体の反復を処理できるようにするという考え方です。
コレクションをポインタから離しておくことが重要です。イテレータはコレクション内の特定の場所を指しているため、コレクションの不可欠な部分ではありません。このようにして、たとえば、同じコレクションに対して複数のイテレータを使用できます。
この分離の欠点は、反復子が反復するコレクションに加えられた変更を認識しないことです。したがって、コレクションの構造を変更して、イテレータが「苦情」なしに作業を続行することを期待することはできません。
インタレータの複数のインスタンスを同時に使用できます。基になるデータのローカルカーソルとしてそれらにアプローチします。
ところで:具体的な実装よりもインターフェースを優先すると、結合が緩みます
イテレータのデザインパターンを探してください。ここで: http://en.wikipedia.org/wiki/Iterator
Iterator
インターフェースを使用すると、そのメソッドを実装するすべてのクラスがイテレーターとして機能できるようになります。 Javaのインターフェースの概念は、ある意味で、インターフェースをimplements
するクラスで特定の機能を提供し、次のように動作するという契約上の義務を負うことです。有効なクラスであるためには契約上の義務が満たされる必要があるため、クラスimplements
を参照する他のクラスは、クラスがそれらの特定の機能を備えていることを知って安心します。
この例では、LinkedList
クラス自体にメソッド(hasNext(), next(), remove()
)を実装するのではなく、LinkedList
クラスがimplements
Iterator
を宣言します。インターフェースなので、他の人はLinkedList
がイテレーターとして使用できることを知っています。次に、LinkedList
クラスはIterator
インターフェース(hasNext()
など)からメソッドを実装するため、イテレーターのように機能できます。
言い換えれば、インターフェースの実装は、特定のクラスがそれが主張するものであるために必要なものを持っていることを他の人に知らせるためのオブジェクト指向プログラミングの概念です。
この概念は、インターフェースを実装するクラスによって実装されなければならないメソッドを持つことによって実施されます。これにより、Iterator
インターフェイスを実装するクラスを使用したい他のクラスが、hasNext()
などのイテレータが持つべきメソッドを実際に持つようになります。
また、Javaには多重継承がないため、インターフェースを使用してその機能をエミュレートできることに注意してください。複数のインターフェースを実装することで、サブクラスであるクラスを持つことができます。一部の機能を継承すると同時に、インターフェイスを実装して別の機能を「継承」する1つの例として、逆に繰り返すことができるLinkedList
というReversibleLinkedList
クラスのサブクラスが必要な場合があります。順序については、ReverseIterator
というインターフェイスを作成し、それがprevious()
メソッドを提供するように強制する場合があります。LinkedList
はすでにIterator
を実装しているため、新しいリバーシブルリストは実装されているはずです。 Iterator
インターフェースとReverseIterator
インターフェースの両方。
インターフェイスの詳細については、 インターフェイスとは何ですか? from The Java Tutorial fromSun。
データ構造ではないものを繰り返し処理している可能性があるためです。サーバーから結果を取得するネットワークアプリケーションがあるとしましょう。これらの結果の周りにIteratorラッパーを返し、Iteratorオブジェクトを受け入れる任意の標準コードを介してそれらをストリーミングすることができます。
これは、優れたMVC設計の重要な部分と考えてください。データは、何らかの方法でモデル(つまりデータ構造)からビューに移動する必要があります。イテレータを仲介として使用すると、モデルの実装が公開されることはありません。 LinkedListをメモリに保持したり、復号化アルゴリズムから情報を引き出したり、JDBC呼び出しをラップしたりすることができます。ビューはイテレータインターフェイスのみを考慮しているため、ビューには関係ありません。
イテレータを使用することの長所と短所について説明している興味深い論文:
OO練習。あらゆる種類のイテレータを処理するコードを作成でき、独自のデータ構造やイテレータを実装する汎用クラスを作成する機会も得られます。インターフェイス。その背後にある実装の種類について心配する必要はありません。
ご存じない場合は、M2Cだけです。 for-each ループで十分な状況では、イテレータインターフェイスを直接使用しないようにすることができます。
最終的に、Iteratorは、多数のデータ構造に適用可能なコントロールの抽象化をキャプチャするためです。あなたが圏論fuに興味があるなら、あなたはこの論文によってあなたの心を吹き飛ばすことができます: イテレーターパターンの本質 。
最初の箇条書きでは、マルチスレッド(または失敗した場合はシングルスレッド)のアプリケーションで、同時実行性違反のためにコレクションをロックする必要がないようです。たとえば、.NETでは、IEnumerableメソッドとオーバーライドメソッドをロックまたは継承せずに、コレクション(またはリストまたは任意のIEnumerable)を同時に列挙および変更することはできません(例外が発生します)。
Java.util.IteratorインターフェースはJavaコレクションフレームワークで使用され、コレクションを繰り返し処理しながらコレクションを変更できるようにします。コレクション全体をきれいに繰り返したい場合は、forを使用します。 -代わりにそれぞれですが、イテレータの利点は、オプションのremove()操作であり、add()およびset()操作も提供するListIteratorインターフェイスにさらに適しています。これらのインターフェイスの両方で次のことができます。コレクションを反復処理すると同時に構造的に変更する。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()メソッドを介して同時に(同時に)リストを変更しない限り。
イテレータは、アイテムのコレクションを調べる一般的な方法を追加するだけです。優れた機能の1つは、繰り返し処理しているリストから要素を削除できるi.remove()です。通常、リストからアイテムを削除しようとすると、奇妙な効果やスローと例外が発生します。
インターフェースは、それを実装するすべてのものの契約のようなものです。あなたは基本的に言っています..イテレータを実装するものはすべて、同じように動作するこれらのメソッドを持つことが保証されています。コードで処理するのがそれだけである場合は、これを使用してイテレータタイプを渡すこともできます。 (リストのタイプを気にしないかもしれません。イテレータを渡したいだけです)これらすべてのメソッドをコレクションに個別に配置できますが、それらが同じように動作すること、または同じ名前を持っていることを保証するものではありません。署名。
イテレータは、Javaで利用できる多くのデザインパターンの1つです。デザインパターンは、便利なビルディングブロック、スタイル、コード/構造の使用法と考えることができます。
Iteratorのデザインパターンの詳細については、Iteratorや他の多くのデザインパターンについて説明しているこのWebサイトを確認してください。 Iteratorのサイトからの抜粋は次のとおりです。 http://www.patterndepot.com/put/8/Behavioral.html
イテレータは、最も単純で最も頻繁に使用されるデザインパターンの1つです。 Iteratorパターンを使用すると、データの内部表現の詳細を知らなくても、標準のインターフェイスを使用してデータのリストまたはコレクションを移動できます。さらに、特別な処理を実行し、データコレクションの指定された要素のみを返す特別なイテレータを定義することもできます。
イテレータは、Javaでコレクションを処理する場合に役立ちます。
使用する For-Each コレクション、配列、またはリストを反復処理するためのloop(Java1.5)。
イテレータは、あらゆる種類のコレクションに対して使用できます。これらを使用すると、基礎となる実装に関係なく、アイテムのコレクションに対してアルゴリズムを定義できます。これは、リスト、セット、文字列、ファイル、配列などを処理できることを意味します。
今から10年後、リストの実装をより適切な実装に変更できますが、アルゴリズムはそれに対してシームレスに実行されます。