Javaの勉強を本格的に始めたときから気になっていたラムダ式とStream APIについて解説したいと思います。これらはJava8で導入された機能で、これによってJavaの文法が大きく変わることになったと言われています。
ラムダ式
後述のStream APIでは処理の内容を記述する際にラムダ式という記法が多く使われます。無名関数と呼ばれることもありますが、引数と処理だけを記述することで簡単にメソッドを定義することができるものです。さっそくですが基本的な書き方はこのようになっています。
(引数) -> {処理}
例えば2つのint型の引数を受け取ってその和を返す場合、以下のようになります。
(int i, int j) -> {return i + j;}
さらに引数については型を省略することができます。ラムダ式はそもそも関数型インタフェースが1つだけ持っている抽象メソッドを実装しているので、その定義から引数の型は判別できるため省略可能になっています。
またラムダ式の処理が1つだけの場合はreturnや中括弧、セミコロンが省略できます。そのため諸々を省略すると最終的には以下のような式で記述することができます。
(i, j) -> i + j
非常に簡潔でわかりやすいですよね。
Stream API
Stream APIはJava8で導入され、ListやMapといったコレクションを効率的に扱うことができます。基本的にはコレクションなどに対してStreamインスタンスを作成し、中間操作を複数回行ない、終端操作によって結果を得る流れとなります。ここでは各操作について内容を見ていきましょう。
作成
まずはじめにStreamインスタンスを作成して、Stream APIを開始します。こちらはよく使われるListからStreamを作成しています。
List<String> list = new ArrayList<>();
list.add("sample1");
list.add("sample2");
list.add("sample3");
list.stream();
単純にStreamを作成しただけなので、特に出力はありません。こちらに対して操作を加えていきます。
中間操作
作成したStreamが持つメソッドを実行する部分です。これらは関数型インタフェースを引数に持つので、引数部分をラムダ式で記述することが可能になっています。ここでは使用することが多いmapメソッドを例にしています。mapは要素を置き換える処理を行ないます。
List<String> list = new ArrayList<>();
list.add("sample1");
list.add("sample2");
list.add("sample3");
list.stream().map(x -> x.toUpperCase()); //各要素を大文字に変換
toUpperCaseメソッドによってListの各要素の文字列を大文字に変換しています。
ちなみに最後の行のラムダ式は「メソッド参照」という記法によってさらにシンプルに表すことが可能です。
list.stream().map(String::toUpperCase);
文法としては「クラス名::メソッド名」のようになっています。
mapの他にもよく使われるものとしてfilterメソッドなどがあります。これは以下のようにして条件を満たす要素のみを取り出すことができます。
List<String> list = new ArrayList<>();
list.add("sample1");
list.add("sample2");
list.add("sample3");
list.stream().filter(x -> x.length() > 3); //文字数が3より大きい要素のみ抽出
こちらは引数部分を必ずboolean型で返す必要があります。

終端操作
中間操作を行ったStreamに対して終端操作で出力をします。まずは各要素に対して操作を行なうforEachメソッドです。
List<String> list = new ArrayList<>();
list.add("sample1");
list.add("sample2");
list.add("sample3");
list.stream().map(String::toUpperCase).forEach(System.out::println); //各要素を標準出力
SAMPLE1
SAMPLE2
SAMPLE3
また操作した結果を集約して取り出すcollectメソッドなどもよく使われます。ここではmapで変換した結果を最終的に新たなListにして返しています。
List<String> list = new ArrayList<>();
list.add("sample1");
list.add("sample2");
list.add("sample3");
list.stream().map(String::toUpperCase).collect(Collectors.toList()); //Listにまとめる
引数としては多くの場合、java.util.stream.Collectorsクラスのメソッドが使われます。
参考文献
上記の解説はこちらの「Java本格入門」を参考にさせていただいています。ラムダ式やStream APIだけでなく、コレクションやマルチスレッドといった実用的な部分について詳しく書かれています。Javaの基本文法について学んだあと、業務等に生かせる知識をさらに身に付けたいと思っている方にはこの上ない解説本になっていておすすめです!
まとめ
今回は日々Javaと向き合っている方に向けて、ラムダ式やStream APIといった比較的新しい機能について主な使い方をご説明しました。これまでのコレクション操作を全てStreamで置き換える必要はありませんが、より効率的で可読性の高いコードにするためにぜひ積極的に使ってみてください。Javaエンジニアとしてのレベルを一段高めることができますよ。
読んでいただきありがとうございました。