Javaでのイテレータのガイド
1. 序章
Iterator は、コレクションをトラバースできる多くの方法の1つであり、すべてのオプションとして、長所と短所があります。
これは、列挙型の代わりとしてJava1.2で最初に導入されました。
- 改善されたメソッド名を導入
- 繰り返し処理しているコレクションから要素を削除できるようになりました
- 反復順序を保証するものではありません
このチュートリアルでは、単純な Iterator インターフェースを確認して、さまざまなメソッドの使用方法を学習します。
また、いくつかの興味深い機能を追加する、より堅牢なListIterator拡張機能も確認します。
2. イテレータインターフェイス
まず、コレクションからイテレータを取得する必要があります。 これは、 iterator()メソッドを呼び出すことによって行われます。
簡単にするために、リストからIteratorインスタンスを取得します。
List<String> items = ...
Iterator<String> iter = items.iterator();
Iterator インターフェースには、次の3つのコアメソッドがあります。
2.1. hasNext()
hasNext()メソッドを使用して、反復する要素が少なくとも1つ残っているかどうかを確認できます。
whileループの条件として使用するように設計されています。
while (iter.hasNext()) {
// ...
}
2.2. next()
next()メソッドは、次の要素をステップオーバーして取得するために使用できます。
String next = iter.next();
next()を呼び出す前に、 hasNext()を使用することをお勧めします。
コレクションのイテレータは、特定の実装で提供されない限り、特定の順序での反復を保証しません。
2.3. remove()
最後に、コレクションから現在の要素を削除する場合は、 remove:を使用できます。
iter.remove();
これは、ConcurrentModificationException。のリスクなしにコレクションを反復処理しながら要素を削除する安全な方法です。
2.4. 完全なイテレータの例
これで、それらすべてを組み合わせて、コレクションのフィルタリングに3つの方法を一緒に使用する方法を確認できます。
while (iter.hasNext()) {
String next = iter.next();
System.out.println(next);
if( "TWO".equals(next)) {
iter.remove();
}
}
これは、私たちが一般的にイテレータを使用する方法です。別の要素があるかどうかを事前にチェックし、それを取得してから、何らかのアクションを実行します。
2.5. ラムダ式で反復する
前の例で見たように、すべての要素を調べて何かを実行したい場合は、Iteratorを使用するのは非常に冗長です。
Java 8以降、ラムダを使用して残りの要素を処理できるforEachRemainingメソッドがあります。
iter.forEachRemaining(System.out::println);
3. ListIteratorインターフェース
ListIterator は、リストを反復処理するための新しい機能を追加する拡張機能です。
ListIterator<String> listIterator = items.listIterator(items.size());
この場合はリストの最後である開始位置を提供する方法に注意してください。
3.1. hasPrevious()および previous()
ListIterator は後方トラバーサルに使用できるため、 hasNext()および next()と同等のものを提供します。
while(listIterator.hasPrevious()) {
String previous = listIterator.previous();
}
3.2. nextIndex()および previousIndex()
さらに、実際の要素ではなく、インデックスをトラバースできます。
String nextWithIndex = items.get(listIterator.nextIndex());
String previousWithIndex = items.get(listIterator.previousIndex());
これは、現在変更しているオブジェクトのインデックスを知る必要がある場合、または削除された要素の記録を保持したい場合に非常に役立ちます。
3.3. add()
add メソッド。名前が示すように、next()によって返されるアイテムの前とprevious()によって返されるアイテムの後に要素を追加できます。
listIterator.add("FOUR");
3.4. set()
言及する価値のある最後のメソッドは、 set()、です。これにより、 next()または previous()の呼び出しで返された要素を置き換えることができます。
String next = listIterator.next();
if( "ONE".equals(next)) {
listIterator.set("SWAPPED");
}
これは、add()またはremove()への以前の呼び出しが行われなかった場合にのみ実行できることに注意することが重要です。
3.5. 完全なListIteratorの例
これらすべてを組み合わせて、完全な例を作成できます。
ListIterator<String> listIterator = items.listIterator();
while(listIterator.hasNext()) {
String nextWithIndex = items.get(listIterator.nextIndex());
String next = listIterator.next();
if("REPLACE ME".equals(next)) {
listIterator.set("REPLACED");
}
}
listIterator.add("NEW");
while(listIterator.hasPrevious()) {
String previousWithIndex
= items.get(listIterator.previousIndex());
String previous = listIterator.previous();
System.out.println(previous);
}
この例では、ListからListIteratorを取得することから始めます。次に、インデックス– のいずれかによって次の要素を取得できます。これにより、イテレータの内部の現在の要素は増加しません。 –またはnextを呼び出します。
次に、特定のアイテムを set に置き換え、add。で新しいアイテムを挿入できます。
反復の終わりに達した後、戻って追加の要素を変更するか、単に下から上に印刷することができます。
4. 結論
Iterator インターフェースを使用すると、コレクションをトラバースしながらコレクションを変更できます。これは、単純なfor/whileステートメントではより困難です。 これにより、良好な凝集度と低結合度を維持しながら、コレクション処理のみを必要とする多くのメソッドで使用できる優れたパターンが得られます。
最後に、いつものように、完全なソースコードはGitHubで入手できます。