Javaのイテレータガイド
1前書き
Iterator
はコレクションをトラバースすることができる多くの方法のうちの1つです、そしてあらゆるオプションとして、それはその長所と短所を持ちます。
これは、最初に
Enumerations
および次のものとしてJava 1.2で導入されました。
-
改良されたメソッド名を導入
-
link:/java-concurrentmodificationexception[削除することを可能にした
繰り返し行っているコレクションの要素]** 繰り返しの順序を保証するものではありません
このチュートリアルでは、簡単な
Iterator
インターフェイスを見て、さまざまな方法を使用する方法を学びます。
また、いくつか興味深い機能を追加した、より堅牢な
ListIterator
拡張機能も確認します。
2
Iterator
インターフェース
はじめに、
Collection
から
Iterator
を取得する必要があります。これは
iterator()
メソッドを呼び出すことによって行われます。
簡単にするために、リストから
Iterator
インスタンスを取得します。
List<String> items = ...
Iterator<String> iter = items.iterator();
Iterator
インターフェースには3つのコアメソッドがあります。
2.1.
hasNext()
hasNext()
メソッドは、繰り返し処理する要素が少なくとも1つ残っているかどうかを確認するために使用できます。
while
ループの条件として使用するように設計されています。
while (iter.hasNext()) {
//...
}
2.2.
次()
next()
メソッドは、次の要素をステップオーバーして取得するために使用できます。
String next = iter.next();
-
next()
を呼び出す前に
hasNext()
を使用することをお勧めします。**
Collectionsの
Iterators__は、特定の順序での繰り返しを保証するものではありません。
2.3.
remove()
最後に、現在の要素をコレクションから削除したい場合は、__removeを使用できます。
iter.remove();
これは、リンクのリスクなしにコレクションを反復処理しながら要素を削除するための安全な方法です。/java-concurrentmodificationexception[
ConcurrentModificationException.
]
2.4. フル
イテレーター
例
これらすべてを組み合わせて、コレクションフィルタリングのために3つの方法を一緒に使用する方法を見てみましょう。
while (iter.hasNext()) {
String next = iter.next();
System.out.println(next);
if( "TWO".equals(next)) {
iter.remove();
}
}
これが私たちがよく使う
Iteratorです。
別の要素があるかどうかを事前にチェックし、それを取得してからそれに対して何らかのアクションを実行します。
2.5. ラムダ式を使った繰り返し
前の例で見たように、すべての要素を調べて何かをしたいだけの場合は、
Iterator
を使用するのが非常に冗長です。
Java 8以降、ラムダを使用して残りの要素を処理することを可能にする
forEachRemaining
メソッドがあります。
iter.forEachRemaining(System.out::println);
3
ListIterator
インターフェース
ListIterator
は、リストを反復処理するための新しい機能を追加する拡張機能です。
ListIterator<String> listIterator = items.listIterator(items.size());
この場合は
List.
の末尾となる開始位置を指定する方法に注目してください。
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()です。これは、
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
を取得し、次にindex –
(反復子の内部の現在の要素を増やすことはありません
)または
next
を呼び出して、次の要素を取得できます。
それから、特定の項目を
set
で置き換え、新しい項目を
add.
で挿入します。
繰り返しの終わりに達した後、追加の要素を修正するために後ろに戻るか、あるいは単にそれらを下から上に印刷することができます。
4結論
Iterator
インターフェースを使用すると、コレクションを移動しながらコレクションを変更できます。これは、単純なfor/whileステートメントではより困難です。これにより、結束力と低結合を維持しながら、コレクション処理のみを必要とする多くの方法で使用できる優れたパターンが得られます。
最後に、いつものように完全なソースコードが入手可能ですhttps://github.com/eugenp/tutorials/tree/master/core-java/[GitHubで利用]