更新日:
Javaのループ処理としてよく出てくるのがfor文ですが、Java8から新しくforEachメソッドが使えるようになりました。すでに便利なものとして使われている拡張for文と比較しながら、forEachメソッドをご紹介します。
forEachメソッドとは
Java8から使えるようになったforEachメソッドはfor文と同様に、繰り返し処理で利用されるメソッドです。ListやMapと組み合わせて使い、順番に値を格納したり、出力したりする際に使用されます。
以下がサンプルのコードです。
リストにそれぞれの値を追加した後、System.outで表示します。
import java.util.ArrayList;
import java.util.List;
public class fugafuga{
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“for”);
list.add(“each”);
list.add(“メソ”);
list.add(“ッド”);
// forEachメソッド
System.out.println(“forEachメソッドの場合”);
list.forEach(s -> System.out.println(s));
}
}
拡張for文との違い
繰り返し処理を行なうという意味では拡張for文もforEachも同じです。配列やコレクションと組み合わせて使用し、ループ処理を行ないながら順番に処理していきます。
List型の配列sから順番に文字列を出力する処理が以下のサンプルコードです。forEachメソッドでは要素の型の定義が不要となり、省略してコードを書けます。
//拡張for文の場合のコード
for (String s : list) {
System.out.println(s);
}
//forEachメソッドの場合のコード
System.out.println(“forEachメソッド”);
list.forEach(s -> System.out.println(s));
結果として出力される内容は同じですが、forEachメソッドの方が単純な書き方を採用しており直感的にコードを認識できるのがメリットです。
forEachメソッドの利用方法
forEachメソッドは、
コレクション名(変数名).forEach(引数 -> 繰り返し処理(引数))
の形で表記します。
よく組み合わせて使われるものと一緒に、forEachメソッドの利用方法についてサンプルコードを用いながらご紹介します。
配列でforEachメソッドを利用する方法
forEachメソッドを配列で利用する場合は、StreamAPIも一緒に使う必要があります。記述方法はほとんど同じです。サンプルコードでご確認ください。
import java.util.Arrays;
public class hogefuga {
public static void main(String[] args) {
String[] strArray = { “りんご”, “みかん”, “バナナ”};
Arrays.stream(strArray).forEach(s -> System.out.println(s));
}
}
ListでforEachメソッドを利用する方法
先にListに「りんご」「みかん」「バナナ」の3つの要素を格納しておき、forEachメソッドで順番に出力するコードのサンプルです。
import java.util.ArrayList;
import java.util.List;
public class hogefuga {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“りんご”);
list.add(“みかん”);
list.add(“バナナ”);
// forEachメソッド
list.forEach(s -> System.out.println(s));
}
}
MapでforEachメソッドを利用する方法
Hashmapに値を格納し、keyとvalueの両方を出力するサンプルコードです。foreachメソッドでは第一引数がkey、第二引数がvalueになります。
import java.util.HashMap;
import java.util.Map;
public class hogefuga {
public static void main(String[] args) {
Map
map.put(“apple”, “りんご”);
map.put(“orange”, “みかん”);
map.put(“banana”, “バナナ”);
map.forEach((key, value) -> System.out.println(key + ” : ” + value));
}
}
forEachメソッドを利用するうえでの注意点
forEachメソッドを利用する際の注意点について紹介します。
contineではなくreturnを利用する
for文で使われるcontinueをforEachメソッドで使うとエラーになります。forEachメソッドではreturnを使って結果を返しましょう。
以下のサンプルコードはリストの値が”りんご”になったとき、りんごを飛ばして、みかんとバナナのみ出力するコードです。
import java.util.ArrayList;
import java.util.List;
public class hogefuga {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“りんご”);
list.add(“みかん”);
list.add(“バナナ”);
// forEachメソッド
list.forEach(s -> {
if(s.equals(“りんご”)){
return;
}
System.out.println(s);
});
}
}
breakではなく例外処理を利用する
forEachメソッドは処理を中断するbreak文も使えません。continueはreturnで代用が可能でしたが、breakは簡単な代替案が現状存在しません。例外処理で書けないことはありませんが、少ない行数でコーディングできるforEachメソッドのメリットを潰してしまっています。
breakが必要な際は、他のメソッドを使うことを検討しましょう。
行数が多くなることを、以下のサンプルコードでご確認ください。みかんが出るとexceptionをthrowするので、バナナは出力されません。
import java.util.ArrayList;
import java.util.List;
public class hogefuga {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“りんご”);
list.add(“みかん”);
list.add(“バナナ”);
try {
list.forEach(s -> {
if (s.equals(“みかん”)) {
throw new RuntimeException();
}
System.out.println(s);
});
} catch (RuntimeException e) {
}
}
}
インデックス番号を取得できない
forEachメソッドはループカウンタを持っていないため、インデックス番号を取得して処理を制御できません。そのため別の方法でカウンタとなる番号を持つ必要があります。
代表的な例として、indexOfメソッドを使う方法と、ループカウンタとして変数を使う方法の2種類をご紹介します。
indexOfメソッドでインデックス番号を取得できますが、同じ要素が複数ある場合は注意が必要です。初めのインデックス番号が表示されてしまうため、同じ値が入ってくることが想定される配列やリストなどの管理には向いていません。
import java.util.ArrayList;
import java.util.List;
public class hogefuga {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“りんご”);
list.add(“みかん”);
list.add(“バナナ”);
list.forEach(s -> System.out.println(list.indexOf(s) + ” : ” + s));
}
}
変数を一つループカウンタとして使用し、カウントアップしていくこともできます。うっかりカウンタとなる変数までループの中に入れると無限ループになるため気をつけましょう。
以下のサンプルコードは変数iをカウンタとして使っており、forEachで一つ出力するごとに、iが1ずつ増えていきます。
import java.util.ArrayList;
import java.util.List;
public class hogefuga {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add(“りんご”);
list.add(“みかん”);
list.add(“バナナ”);
int[] i = { 0 };
list.forEach(s -> {
System.out.println(i[0] + ” : ” + s);
i[0]++;
});
}
}
まとめ
forEachメソッドは拡張for文と比べて、省略した書き方が可能であり、限られた容量の中でコーディングしなければならないときなどに向いています。breakなど他の繰り返し構文でよく使われるものが使えないこともあるため、できないことはきちんと把握して使うのがコツです。
コードを単純化して見やすくもしてくれるforEach文をぜひ使ってみましょう。