Java でコレクションを学習しているときに、コレクション レベルのルート インターフェイス Collection が Iterable
1. イテレーター Iterator
インターフェース: Iterator
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }
Iterator インターフェース API を見ると、これがコレクションを反復するためのイテレーターであることがわかります。イテレーターを使用すると、呼び出し元は、明確に定義されたセマンティクスを使用して、反復中にイテレーターが指すコレクションから要素を削除できます。
特に注意すべき点は、このイテレータの Remove() メソッドの使用です。イテレータによって返された最後の要素 (オプションの操作) を、イテレータが指すコレクションから削除します。このメソッドは、next の呼び出しごとに 1 回だけ呼び出すことができます。このメソッド (remove メソッド) の呼び出し以外の方法で反復中にイテレーターが指すコレクションが変更された場合、イテレーターの動作は未定義です。 インターフェイス設計者は、Iterator
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String lang = iterator.next(); list.remove(lang);//will throw ConcurrentModificationException } } }
このコードは、イテレータの実行中に要素を削除するためにイテレータのremove()メソッドを使用せず、ArrayListを使用するため、実行時にConcurrentModificationException例外をスローします。 Remove() メソッドは、イテレータが指すコレクションを変更します。これはイテレータの設計原則に違反するため、例外が発生します。
報告された例外は次のとおりです:
スレッド「メイン」の例外 java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList $ Itr.next(ArrayList.java:831)
at Text.ItaratorTest.main(ItaratorTest.java:17)
2. for-each ループとイテレータ Iterator
Java5 以降、Java では for を使用-each ループ、コレクションと配列をループするために使用できます。 Foreach ループを使用すると、従来の for ループでインデックスを維持したり、イテレータ / ListIterator (ArrayList のイテレータ実装) を使用するときに while ループで hasNext() メソッドを呼び出すことなく、コレクションを反復処理できます。 for-each ループにより、コレクションまたは配列を走査するプロセスが簡素化されます。ただし、foreach ループを使用する場合は注意すべき点が 2 つあります。
foreach ループを使用するオブジェクトは Iterable
次の例を参照してください:
import java.util.ArrayList; public class ForeachTest1 { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); // What does this code will do, print language, throw exception or // compile time error for (String language : myCollection) { System.out.println(language); } } private class CustomCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(T o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(T o) { return bucket.remove(o); } } }
コード内の CustomCollection クラスが Iterable
スレッド "main" java.lang.Error の例外: 未解決のコンパイルの問題:
での配列または java.lang.Iterable
のインスタンスのみを反復処理できます。 Text.ForeachTest1.main(ForeachTest1.java:15)
実際、このコードを記述した後、Eclipse はエラーを見つけるために foreach ループにエラーを表示します。配列または java.lang.Iterable のインスタンス
上記の例から、foreach ループは Iterable
import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Iterator; public class ForeachTest { public static void main(String args[]) { CustomCollection<String> myCollection = new CustomCollection<String>(); myCollection.add("Java"); myCollection.add("Scala"); myCollection.add("Groovy"); for (String language : myCollection) { System.out.println(language); } } private static class CustomCollection<T> extends AbstractCollection<T> { private ArrayList<T> bucket; public CustomCollection() { bucket = new ArrayList(); } public int size() { return bucket.size(); } public boolean isEmpty() { return bucket.isEmpty(); } public boolean contains(Object o) { return bucket.contains(o); } public boolean add(T e) { return bucket.add(e); } public boolean remove(Object o) { return bucket.remove(o); } @Override public Iterator<T> iterator() { // TODO Auto-generated method stub return bucket.iterator(); } } }
2. foreach ループの内部実装も Iterator に依存します
foreach ループが内部実装として Iterator を使用するという事実を確認するために、引き続き次の例を使用します。検証用のこの記事:
public class ItaratorTest { public static void main(String[] args) { Collection<String> list = new ArrayList<String>(); list.add("Android"); list.add("IOS"); list.add("Windows Mobile"); // example1 // Iterator<String> iterator = list.iterator(); // while (iterator.hasNext()) { // String lang = iterator.next(); // list.remove(lang); // } // example 2 for (String language : list) { list.remove(language); } } }
プログラムの実行中に例外が報告されました:
スレッド「メイン」の例外 java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList $Itr.next(ArrayList.java:831)
at Text.ItaratorTest.main(ItaratorTest.java:22)
この例外は、Iterator が for-each ループ内で使用されていることを示しています。 Collection を走査し、Iterator .next() も呼び出します。これにより、(要素の) 変更がチェックされ、ConcurrentModificationException がスローされます。
概要:
コレクションを走査するときに、走査中にコレクションを変更したい場合は、Iterator/listIterator を使用して変更する必要があります。そうしないと、「未確定の結果」が発生する可能性があります。
foreach ループはイテレータを通じて実装され、foreach ループを使用するオブジェクトは Iterable インターフェイスを実装する必要があります
以上がこの記事の全内容です。皆さんの学習に役立つことを願っています。また、皆さんも PHP 中国語 Web サイトをサポートしていただければ幸いです。
JAVA の for-each ループと反復に関連する詳細な記事については、PHP 中国語 Web サイトに注目してください。