
Javaには、クラスの宣言とインスタンス化を同時に行うことができる「匿名クラス」という文法が存在するとご紹介させて頂きました。
また、Java8からは、下記の記事で解説させて頂きました通り、「関数オブジェクト」を使えば変数に関数を代入できると学びました。
これらの技術の応用技術として、Java8から使うことができる「ラムダ式」という技術をご紹介させていただきます。
「ラムダ式」を理解するには、「匿名クラス」と、「関数オブジェクト」の理解が必須ですので、まだ理解されていない方は、先にそちらを理解しましょう。
実際にラムダ式を使って見ましょう。
下記のようになります。
サンプル
1 2 3 4 5 6 |
public class Main { public static void main(String args[]) { IntBinaryOperator ramda = (int a,int b) -> {return a + b;}; System.out.println(ramda.applyAsInt(2,4)); } } |
実行結果
解説
IntBinaryOperator ramda = (int a,int b) -> {return a + b;};
「IntBinaryOperator」は、関数オブジェクトのご説明で登場した、int型の引数を2つ取り、int型の戻り値を1つ返す抽象メソッドを持つ、インターフェイスですね。
関数オブジェクトでは、下記の構文を使って、「IntBinaryOperator」型の変数にメソッドを代入するとご説明しましたが、今回は「(int a,int b) -> {return a + b;};」という式を代入しています。(この->が「ラムダ式」です。)
1 |
変数名 = インスタンス変数名::そのインスタンスのメソッド名 |
このクラスの作成と、インスタンス化を同時に実施しているのが、「匿名クラス」と似た仕組みですよね。
ramda.applyAsInt(2,4)
後は、「IntBinaryOperator」の抽象メソッドである、applyAsIntを使って、上記で宣言した「引数の一つ目と二つ目を足し算する処理」の結果を得ています。
ラムダ式の省略記法
引数の型を省略できる。
例えば、下記のように省略が可能です。
1 |
IntBinaryOperator ramda = (a,b) -> {return a + b;}; |
戻り値が一つだけの場合は、returnと波かっこ({})を省略できる。
1 |
IntBinaryOperator ramda = (a,b) -> a + b; |
だいぶ、簡略化されましたね。
ラムダ式のメリット
- インターフェイスの実装のために書かれていた記述をかなり簡略化できる。
- 他人が、ラムダ式を使って書いていたら、理解していなければソースを読むことができない。
- Java8になって、ラムダ式を使えることが前提のAPIが増えてきており、理解しなければ今後Javaプログラマーとして危うい。
これを見ると、何か流行に流されているだけで、イマイチメリットがないのでは?と思われるかもしれませんね。
確かに、これらのメリットは、大幅にコーディングを楽にしてくれるというものではなく、理由も少し後ろ向きのような気がします。
ただ、実際に効果を発揮するのは、同じくJava8から導入されたStreamAPIを使う時です。
StreamAPI
Java8以降で使える文法になりますが、StreamAPIというものをご紹介させて頂きます。
StreamAPIは、従来からある「InputStream」や「OutputStream」とは全く別物なので、注意しましょう。
前回の記事でラムダ式をご紹介させて頂きましたが、ラムダ式が真価を発揮するのは、StreamAPIで、コレクションや、配列に対して一括処理をする場合になります。
実際に使ってみる。
StreamAPIを使う前のリスト処理
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Main { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("test"); list.add("test1"); for(String li:list) { System.out.println(li); } } } |
StreamAPIを使った後のリスト処理
1 2 3 4 5 6 7 8 9 10 11 |
public class Main { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("test"); list.add("test1"); list.stream().forEach(li -> System.out.println(li)); } } |
非常に、シンプルにループ文を記述できていることがわかりますね。
解説
Java8からは、ArrayListやHashSet等の「java.util.Collection」に属しているクラスは、全て「stream()メソッド」を持つようになりました。
streamメソッド
コレクションの各要素に、一括で処理を行ったりできる等のStreamのインスタンスを得ることができます。
forEachメソッド
Streamインスタンスの代表的メソッドの一つです。
一つの関数オブジェクトを受け取り、コレクションの各要素に、関数を実行してくれます。
まとめ
今回、ご紹介させて頂いたのは、StreamAPIのほんの一例です。
他にも、非常に多くのAPIがあるので、興味のある方は勉強してみて下さい。
個人的には、最新のJava8に対応したOracle JavaプログラマーのGold試験で、非常に多くのラムダ式や、Stream APIに関する問題が出題されるので、極めたい方はチャレンジしてもいいかもしれませんね。
この記事へのコメントはありません。