ラムダ式

数学の世界では関数を表現する式にギリシャ文字のラムダ(lambda):λを使う慣習があったそうですが、この名前に由来するラムダ計算という計算体型が1930年代に考案され、1958年に誕生した関数型言語のLISPで関数の定義法として採用され、多くの言語で関数を他の関数の引数として与える操作が許されています。

こういった背景のラムダを冠した表記法:ラムダ式がJava8で導入されました。
ラムダ式を使えば、実装が必要なメソッドを1つだけ持つインターフェース(関数型インタフェース)の実装が、従来の無名クラスを使うよりも簡潔に記述できます

書式

( 実装するメソッドの引数 ) -> { 処理 }

利用例
インターフェース

interface IntFunc {
	public int func(int x);
}

無名クラスによる実装

public class NamelessClass {
      public static void main( String args[] ) {
		IntFunc iNLF = new IntFunc(){
			public int func(int x){
				return x+x;
			}
		};
		System.out.println("NamelessFunc return = " + iNLF.func(2));
	}
}

実行結果

>java NamelessClass
NamelessFunc return = 4

>

ラムダ式による実装

public class LambdaClass {
      public static void main( String args[] ) {
		IntFunc iLF = (int x) -> {return x+x;};
		System.out.println("LambdaFunc return = " + iLF.func(2));
	}
}

無名クラスでは5行の記述が、ラムダ式では僅か1行で記述できます。

実行結果

>java LambdaClass
LambdaFunc return = 4

>

ラムダ式の基本書式は、引数には型を明示し、処理は{ }で囲みます。

(int x, int y) -> {
	return x + y;
};

しかし、条件によりラムダ式はさらに簡略記述できます。

引数の型定義は省略可能(コンパイラが推測)

(x, y) -> {
	return x + y;
};

処理が1行なら、{ }もreturnも不要

[javat gutter=”false”]
(x, y) -> x + y;
[/java]

引数が1つなら、引数の( )も不要

x -> x * 2;

ただし、引数が無い場合は、( )は必要

() -> 1;

また、Java8では、使用頻度の高い関数型インターフェースがjava.util.functionの中で提供されています。

Supplier系
引数なしで値を返す
Supplier s = () -> “input”;
System.out.println(s.get());
Consumer系
値を受け取るが、返却しない(処理を行う)
SupplierConsumer c = (str) -> System.out.println(str);
c.accept(“output”);
Predicate系
値を受け取って論理値を返す
Predicate p = (str) -> str == “yes”;
System.out.println(p.test(“no”));
Function系
値を受け取って、何らかの値を返す
ToIntFunction f = s -> s.length();
System.out.println(f.applyAsInt(“abc”));
上記全て、引数を2つ受け取る場合はインターフェース名の先頭に「Bi」を付ける
BiFunction lambda5 = (str, num) -> str + num;

さらに、受取るデータ型によりInt、Long、Doubleを名前の先頭に付けたインターフェースがありますし、返すデータ型によりToInt、ToLong、ToDoubleを名前の先頭に付けたインターフェースがあります。

Javaではメソッドを関数と考えられない事もありませんが、メソッドはあくまでクラスの振舞い、機能なのでクラスを意識せずに使うことが出来ません。これに対しラムダ式はインターフェースで規定されたメソッドを、クラスを意識した実装を記述しないで必要な処理だけ記述し、直接使う方法とも考えられるでしょう。

クラスに戻る