ホームページ >Java >&#&チュートリアル >Java の Iterable と Iterator の詳細な紹介
この記事では、Java の Iterable と Iterator について詳しく説明します。必要な方は参考にしていただければ幸いです。
Java では、次の方法で List コレクションを走査できます。
List<Integer> list = new ArrayList<>(); list.add(5); list.add(23); list.add(42); for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + ","); } Iterator it = list.iterator(); while (it.hasNext()) { System.out.print(it.next() + ","); } for (Integer i : list) { System.out.print(i + ","); }
1 つ目は通常の for ループ、2 つ目はイテレータの走査、3 つ目は for each ループです。後の 2 つのメソッドには、Java の反復子オブジェクトと反復可能オブジェクトが含まれます。次に、これら 2 つのオブジェクトの違いと、カスタム クラスでの for each ループの実装方法を見てみましょう。
iterator は Java のイテレータ オブジェクトであり、List などのコレクションを反復処理できる基礎的な依存関係です。 iterable インターフェイスはイテレータを返すメソッドを定義します。これはイテレータをカプセル化することと同じです。同時に、iterable インターフェイスを実装するクラスは各ループをサポートできます。
jdk の Iterator インターフェイスの主なメソッドは次のとおりです。
public interface Iterator<E> { boolean hasNext(); E next(); }
Iterator は、上記の 2 つのメソッドを通じてコレクションへの反復アクセスのメソッドを定義します。 、および特定の実装メソッド さまざまな実装クラスに応じて、特定のコレクション クラスは反復を実装するための Iterator インターフェイスのメソッドを実装します。
List には Iterator インターフェイスが実装されていませんが、Iterable インターフェイスが実装されていることがわかります。 Iterable インターフェイスのソース コードをさらに観察すると、Iterable インターフェイスが Iterator オブジェクトのみを返すことがわかります。
public interface Iterable<T> { Iterator<T> iterator(); }
したがって、次のメソッドを使用して List を反復できます (iterator() メソッドを呼び出すことによって)
Iterator it = list.iterator(); while (it.hasNext()) { System.out.print(it.next() + ","); }
同時に、Iterable インターフェイスを実装する場合は、次のメソッドも使用できます。 for each ループ。
実際、for each ループは Iterator イテレータにも依存しますが、Java によって提供される構文糖である Java コンパイラは、トラバーサルのためにそれを Iterator イテレータに変換します。各ループについて次のコードを逆コンパイルします。
for (Integer i : list) { System.out.println(i); }
逆コンパイル後:
Integer i; for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){ i = (Integer)iterator.next(); }
Java の for each 拡張ループがイテレータを通じて実装されていることがわかります。
質問があります。なぜ hasNext() メソッドと next() メソッドを Iterable インターフェイスや他のクラスに直接配置しないのですか。それらを直接実装できますか?
その理由は、一部のコレクション クラスには複数のトラバーサル メソッドがあるため、Iterable を実装するクラスは、ListItr
や LinkedList
などの複数の Iterator 内部クラスを実装できるためです。 DescendingIterator
2 つの内部クラスは、それぞれ双方向トラバーサルと逆順トラバーサルを実装します。異なる Iterator
を返すことで異なるトラバーサル メソッドを実装すると、より柔軟になります。 2 つのインターフェイスをマージすると、異なる Iterator
実装クラスを返すことができなくなります。 ListItr 関連のソース コードは次のとおりです。
public ListIterator<E> listIterator(int index) { checkPositionIndex(index); return new ListItr(index); } private class ListItr implements ListIterator<E> { ... ListItr(int index) { // assert isPositionIndex(index); next = (index == size) ? null : node(index); nextIndex = index; } public boolean hasNext() { return nextIndex < size; } ...
上記のように、list.listIterator()
メソッド (list.iterator()##) を呼び出すことでイテレータを返すことができます。 # は単なるデフォルト実装です )
DescendingIteratorソース コードは次のとおりです:
public Iterator<E> descendingIterator() { return new DescendingIterator(); } private class DescendingIterator implements Iterator<E> { private final ListItr itr = new ListItr(size()); public boolean hasNext() { return itr.hasPrevious(); } public E next() { return itr.previous(); } public void remove() { itr.remove(); } }このイテレータは
list.descendingIterator()# を通じて使用することもできます。 ##。 独自のイテレータを実装する
ArrayMap<String, Integer> am = new ArrayMap<>(); am.put("hello", 5); am.put("syrups", 10); for (String s: am) { System.out.println(s); }
hashNext と next を実装していないため、抽象メソッドであるため、トラバースすることはできません。
カスタマイズされたイテレータ クラス
public class KeyIterator implements Iterator<K> { private int ptr; public KeyIterator() { ptr = 0; } @Override public boolean hasNext() { return (ptr != size); } @Override public K next() { K returnItem = keys[ptr]; ptr += 1; return returnItem; } }
上に示すように、反復アクセス用の KeyIterator オブジェクトを作成します (外部クラスによって、内部クラスオブジェクト)。
各ループのサポート
反復可能なインターフェイスが実装されていないため、現在は各ループのアクセスをサポートできません。まず ArrayMap に Iterable インターフェイスを実装します。
ArrayMap<String, Integer> am = new ArrayMap<>(); am.put("hello", 5); am.put("syrups", 10); ArrayMap.KeyIterator ami = am.new KeyIterator(); while (ami.hasNext()) { System.out.println(ami.next()); }
public class ArrayMap<K, V> implements Iterable<K> { private K[] keys; private V[] values; int size; public ArrayMap() { keys = (K[]) new Object[100]; values = (V[]) new Object[100]; size = 0; } .... }
カスタム KeyIterator クラスは Iterator インターフェイスを実装する必要があることに注意してください。実装しないと、 iterator() メソッドで返される型は一致しません。
以上がJava の Iterable と Iterator の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。