JavaのIteratorを使用すると、ListやMapなどのコレクションのループ処理が便利になります。
この記事では、Iteratorについて
- Iterator(イテレータ)とは
- Iteratorの使い方
ループ処理でListの要素を
- 追加する方法
- 削除する方法
など基本的な内容から、応用的な処理についても解説します。
今回はIteratorについて、くわしく解説していきます!
なお、Javaの記事については、こちらにまとめています。
Iterator(イテレータ)とは
Iteratorインタフェースは、ListやMapなどのコレクションの要素を、順番に処理する場合に使用します。
Iteratorは、次の要素数がある場合にtrueを返すhasNextメソッドや、次の要素を取得する場合に用いるnextメソッドを用いて、使用します。
ループ処理でMapの要素を操作する方法
ここでは、Iteratorを使ってMapの要素を取得する方法について解説します。
IteratorでMapのkeyを取得する方法
Iteratorを使ってMapのkeyを取得することができます。
サンプルコードで確認していきましょう。
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Mapの宣言
Map<String, Integer> map = new HashMap<String, Integer>();
// Mapに要素を追加
map.put("apple", 100);
map.put("orange", 200);
map.put("melon", 300);
// Iterator<String> の宣言
Iterator<String> key_itr = map.keySet().iterator();
// hasNextを使用して値がある場合はループを継続する
// keyの取得
while(key_itr.hasNext()) {
// nextを使用して値を取得する
String str = (String)key_itr.next();
System.out.println(str);
}
}
}
実行結果:
orange apple melon
このサンプルコードでは、まずHashMapクラスを使って変数mapを宣言し、mapに要素を追加します。
次にIteratorインタフェースのkey_itrを宣言し、keySetメソッドを使ってmapのkey値を取得しています。hasNextメソッドを使用し、次の要素がある場合はtrueを返し、whileによるループを継続させます。nextメソッドを使用し、mapのkeyを取得しています。
なお、HashMapで追加された値は順不同となります。keySetメソッドの使い方についてもっとくわしく知りたい方は、こちらを参照してくださいね!
IteratorでMapのvalueを取得する方法
Iteratorを使ってMapのvalue値も取得することができます。
サンプルコードで確認していきましょう。
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Mapの宣言
Map<String, Integer> map = new HashMap<String, Integer>();
// Mapに要素を追加
map.put("apple", 100);
map.put("orange", 200);
map.put("melon", 300);
// Iterator<Integer> の宣言
Iterator<Integer> val_itr = map.values().iterator();
// valueの取得
while(val_itr.hasNext()) {
// nextを使用して値を取得する
Integer i = (Integer)val_itr.next();
System.out.println(i);
}
}
}
実行結果:
200 100 300
このサンプルコードでは、同じようにしてIteratorインタフェースのval_itrを宣言し、valuesメソッドを使ってmapのvalue値を取得しています。
IteratorでMapのkey、valueをセットで取得する方法
Iteratorを使ってMapのkey、valueをセットで取得することができます。
サンプルコードで確認していきましょう。
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Mapの宣言
Map<String, Integer> map = new HashMap<String, Integer>();
// Mapに要素を追加
map.put("apple", 100);
map.put("orange", 200);
map.put("melon", 300);
// Iterator<Map.Entry<String, Integer>> の宣言
Iterator<Map.Entry<String, Integer>> itr = map.entrySet().iterator();
// key, valueの取得
while(itr.hasNext()) {
// nextを使用して値を取得する
Map.Entry<String, Integer> entry = itr.next();
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
}
実行結果:
orange : 200 apple : 100 melon : 300
このサンプルコードでは、Iteratorインタフェースのitrを宣言し、entrySetメソッドを使ってmapのkey値とvalue値をセットで取得しています。
ループ処理でListの要素を操作する方法
先ほどはIteratorでMapの要素を取得する方法について解説しました。
ここでは、Iteratorを使用してListの要素を順番に取得する処理を解説します。また、Iteratorの応用編として、ListIteratorを使用して値を追加する方法、ループの中で値を削除する方法を詳しく解説していきます!
IteratorでListの要素を取得する方法
ここでは、実際にArrayListクラスで宣言したlistに要素を追加し、Iteratorを使用してlistの要素を順番に取得する処理を解説します。
以下にIteratorの基本的な使い方を記述します。
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<String> list = new ArrayList<String>();
// Listに要素を追加
list.add("apple");
list.add("orange");
list.add("melon");
// Iterator<String> の宣言
Iterator<String> itr = list.iterator();
// hasNextを使用して値がある場合はループを継続する
while(itr.hasNext()) {
// nextを使用して要素を取得する
String str = (String)itr.next();
System.out.println(str);
}
}
}
実行結果:
apple orange melon
このサンプルコードでは、まずArrayListクラスを宣言し、変数listに要素を追加します。次にIteratorインタフェースのitrを宣言し、listの全要素を取得しています。
ListIteratorで要素を追加する方法
Iteratorでループ中に値を追加したい場合、ListIteratorインタフェースを使用します。以下にループ中に値を追加する方法を記述します。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<Integer> list = new ArrayList<Integer>();
// Listに値を追加
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// ListIterator<Integer>の宣言
ListIterator<Integer> itr = list.listIterator();
while(itr.hasNext()) {
Integer num1 = itr.next();
if (num1 == 5) {
itr.add(6);
}
}
System.out.println(list);
}
}
実行結果:
[1, 2, 3, 4, 5, 6]
このサンプルコードでは、まずArrayListクラスを宣言し、変数listに値を追加します。
次にListIteratorインタフェースのitrを宣言し、listの全要素を取得します。Iteratorでのループ中に値が5の場合はaddメソッドを使用して、値を追加しています。
ArrayListの中身を確認すると、6が追加されているのがわかります。
ループ処理で要素を削除する方法
MapやListなどのコレクションをループの中で削除するためには、removeメソッドを使用します。
Iteratorでのループを使用せずに、for文などで要素数分ループして値を削除することも可能ですが、Iteratorメソッドを使用しないと、非効率になったり思わぬ問題が発生する場合があります。
for文で要素数分ループする場合
まずは、以下のようにIteratorメソッドを使用しないで、for文で削除する方法を記述します。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<Integer> list = new ArrayList<Integer>();
// Listに値を追加
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// Listのサイズ分ループする
for(int i=0; i<list.size(); i++) {
// 値が1または4の場合はリストを削除
if (i == 1 || i == 4) {
list.remove(i);
}
}
System.out.println("list = " + list);
}
}
実行結果:
list = [1, 3, 4, 5]
このサンプルコードでは、listを要素数分ループし、値が1または4の場合はremoveメソッドを使用して、値を削除しています。
しかし、実行結果を見る限りでは、実際に削除されている要素は2のみとなっています。
これは、removeメソッドで削除時にi番目(ここでは1番目)を指定していますが、コレクション型は要素数が0から始まるため、実際には2番目の値が削除されてしまいます。
また、listを削除するごとに要素数が1つ減ってしまいます。(0、1、2、3となる)そのため、「i == 4」に到達するこはなく、listの中身を確認すると、要素数2のみが削除された形となってしまいます。
また、sizeメソッドをループ毎に呼び出していますが、メソッドを呼ぶこと自体わずかながら負荷がかかってしまいます。sizeメソッドを使用してのループ処理は、システムの負荷が高まって、予期しない問題が発生する危険性もあります。
とくに膨大なデータ量(何万〜何十万)がある場合は、推奨できません。
for文で保存した要素数分ループする場合
そこで、変数にlistのサイズを保存しておいて、その変数を使うことでメソッドの呼び出し回数を減らしながら、listの要素数分ループ処理をさせるという方法もあります。
以下にサイズを指定してループの中でlistの値を削除するサンプルを記述します。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<Integer> list = new ArrayList<Integer>();
// Listに値を追加
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 毎回sizeメソッドを呼ぶのはシステムの負荷が高まるため、
// 一旦、int型の変数にListのサイズを保存する
int size = list.size();
// Listのサイズ分ループする
for(int i=0; i<size; i++) {
// 値が1または4の場合はリストを削除
if (i == 1 || i == 4) {
list.remove(i);
}
}
System.out.println("list = " + list);
}
}
このサンプルコードを実行すると、”java.lang.IndexOutOfBoundsException”の例外が発生します。
リストのサイズを事前に取得し、リストのサイズ分ループしていますが、ループの中でlistの値を削除した結果、listのサイズの値も減ってしまいます。
そのため、変数sizeで取得したサイズ数分の要素が参照できずに、例外が発生してしまいます。
拡張for文を使う場合
では、拡張for文を使って削除するとどうなるのか?
拡張for文に置き換えてみます。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<Integer> list = new ArrayList<Integer>();
// Listに値を追加
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 拡張for文
for(Integer i : list) {
if (i == 3) {
list.remove(i);
}
}
System.out.println("list = " + list);
}
}
このサンプルコードを実行すると、”java.util.ConcurrentModificationException”の例外が発生します。
これは、ループの中でCollectionの値が変更されると、例外が投げられるためです。
Iteratorでのループ中に要素を削除する場合
for文や拡張for文が発生すると、思わぬ問題や例外が発生することがわかりました。そのため、正確にListの値を削除するためには、Iteratorを使用します。
以下にIteratorでのループ中に値を削除する方法を記述します。
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// Listの宣言
ArrayList<Integer> list = new ArrayList<Integer>();
// Listに値を追加
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// Iterator<Integer> の宣言
Iterator<Integer> itr = list.iterator();
// hasNextを使用して値がある場合はループを継続する
while(itr.hasNext())
{
// nextを使用して値を取得する
Integer num2 = itr.next();
// 値が3の場合
if (num2 == 3)
{
// 値を削除する
itr.remove();
}
}
System.out.println("list = " + list);
}
}
実行結果:
list = [1, 2, 4, 5]
Iteratorでのループ中に値が3の場合は、removeメソッドを使用して値を削除しています。ArrayListの中身を確認すると、意図したとおり3が削除されているのがわかります。
Mapについてもっと詳しく知りたい方へ
Mapのさまざまな使い方については、以下の記事にまとめていますので、ぜひ参考にしてくださいね!
for文でのループ処理について知りたい方へ
今回の解説で使用したfor文でのループ処理についてくわしく知りたい方は、以下の記事にまとめていますので、ぜひ参考にしてくださいね!
while文でのループ処理について知りたい方へ
今回の解説で使用したwhile文でのループ処理についてくわしく知りたい方は、以下の記事にまとめていますので、ぜひ参考にしてくださいね!
まとめ
ここでは、Iteratorを使用した基本的なループ処理や、値の追加や削除の方法、削除時の危険性など説明しました。ListやMapなどの値をループで処理する場合は、Iteratorを使用したほうが、正確に処理をすることが可能です。
もし、Iteratorの使い方を忘れてしまったら、この記事を思い出してくださいね。






