1. イテレータが誕生した背景
についてはすでによくご存知ですHashSet
。レッスンを読むだけでなく、それを本当に調べたなら、次の質問をするべきです。
すべての HashSet 要素のリストを画面に表示するにはどうすればよいですか? 結局のところ、インターフェイスにはメソッドがありませget()
んset()
。
HashSet
この制限に直面しているのは私だけではありません。に加えてHashSet
、要素には順序が定義されていないため、インデックスによる要素の取得を許可しないコレクションが他にもたくさんあります。
長年にわたり、プログラマーはグラフやツリーなどの複雑なデータ構造を多数発明してきました。またはリストのリスト。
多くのコンテナでは、新しい要素が追加されるか、既存の要素が削除されると、要素の順序が変更されます。たとえば、リストには要素が特定の順序で格納され、新しい要素が追加されると、ほとんどの場合リストの中央に挿入されます。
また、要素を格納するコンテナはあるものの、固定された順序ではないという状況も発生します。
ここで、そのようなコレクションのすべての要素を配列またはリストにコピーするとします。すべての要素を取得する必要があります。要素を反復する順序は気にしません。重要なのは、同じ要素を複数回反復しないことです。どうやってそれを行うのでしょうか?
2. コレクションのイテレータ
イテレータは、上記の問題の解決策として提案されました。
イテレータはコレクションに関連付けられた特別なオブジェクトであり、コレクションのすべての要素を繰り返すことなく走査するのに役立ちます。
次のコードを使用して、任意のコレクションのイテレータを取得できます。
Iterator<Type> it = name.iterator();
ここでname
、 はコレクション変数の名前、Type
はコレクションの要素の型、iterator()
はコレクションのメソッドの 1 つ、it
は反復子変数の名前です。
イテレータ オブジェクトには 3 つのメソッドがあります。
方法 | 説明 |
---|---|
|
コレクション内の次の要素を返します |
|
まだ通過していない要素があるかどうかを確認します |
|
コレクションの現在の要素を削除します |
これらのメソッドは、Scanner クラスのnextInt)
およびhasNextInt()
メソッドに似ています。
このnext()
メソッドは、反復子を取得したコレクションの次の要素を返します。
このhasNext()
メソッドは、反復子がまだ返していない追加要素がコレクションにあるかどうかを確認します。
のすべての要素を表示する方法は次のとおりですHashSet
。
コード | ノート |
---|---|
|
HashSet 要素を格納するオブジェクトを作成しますString 。さまざまな言語の挨拶を set 変数に追加します。セットの反復子オブジェクトを取得します set 。要素が残っている限り 次の要素を取得 画面上に要素を表示 |
3.For-each
ループ
イテレータの主な欠点は、コードがfor
ループを使用する場合よりも煩雑になることです。
for
比較するために、ループとイテレータを使用してリストを表示してみましょう。
イテレーター | forループ |
---|---|
|
|
はい、ループを使用して の要素をトラバースするほうがはるかに優れていますArrayList
。すべてが短くなります。
しかし、Java の作成者は再び私たちに砂糖を注ぐことにしました。私たちにとって幸運なことに、それは構文シュガーでした。
彼らは Java に新しい種類のループを与え、それをfor-each
ループと呼びました。一般的には次のようになります。
for(Type name:collection)
ここでcollection
、 はコレクション変数の名前、Type
はコレクション内の要素の型、 はname
ループの各反復でコレクションから次の値を取得する変数の名前です。
この種のループは、暗黙的な反復子を使用してコレクションのすべての要素を反復処理します。実際の動作は次のとおりです。
For-each ループ | コンパイラが認識する内容: イテレータを使用したループ |
---|---|
|
|
コンパイラーはfor-each
コード内にループを検出すると、それを右側のコードに置き換えるだけです。欠落している他のメソッド呼び出しとともにイテレーターを取得するための呼び出しが追加されます。
プログラマはループを好みfor-each
、コレクションのすべての要素を反復処理する必要がある場合は、ほとんどの場合ループを使用します。
ArrayList
ループを使用してリストを反復処理する場合でも、for-each
短く見えます。
For-each ループ | forループ |
---|---|
|
|
for-each
4.ループ内の要素の削除
このfor-each
ループには、要素を正しく削除できないという欠点が 1 つあります。このようなコードを書くとエラーが発生します。
コード | ノート |
---|---|
|
削除操作ではエラーが発生します。 |
これは非常に素晴らしくわかりやすいコードですが、機能しません。
イテレータによるコレクションのトラバース中にコレクションを変更することはできません。
この制限を回避するには 3 つの方法があります。
1. 別の種類のループを使用する
When traversing an ArrayList collection
、カウンター変数を使用して通常のループを使用できますi
。
コード |
---|
|
ただし、このオプションはコレクションには適していませHashSet
んHashMap
。
2. 明示的なイテレータを使用する
イテレータを明示的に使用して、そのremove()
メソッドを呼び出すことができます。
動作するバージョン | 動作しないバージョン |
---|---|
|
|
remove()
イテレータ オブジェクトでメソッドを呼び出していることに注意してください。イテレータは項目が削除されたことを認識しており、状況を正しく処理できます。
3. コレクションのコピーを使用する
コレクションのコピーを作成し、そのコピーをループ内で使用してfor-each
、元のコレクションから要素を削除することもできます。
コード | ノート |
---|---|
|
コレクションのコピーの作成は非常に簡単です。 ループはコレクションのコピーに反復子を使用します。 要素がコレクションから削除されます list 。 |
要素自体は複製されないため、コレクションはかなり早くコピーされます。代わりに、新しいコレクションには、古いコレクションにすでに存在する要素への参照が格納されます。
GO TO FULL VERSION