日々常々

ふつうのプログラマがあたりまえにしたいこと。

Lambdaの書き方をさくっと

関西ジャバで「どうでもいい」と言われた Lambda の書き方をさくっと書いておきます。

「来年の事を言えば鬼が笑う」とか言いますが、もう今年なんで大丈夫です*1

Lambda expression

Functional Interface を実装する無名内部クラスの代わりに使えるモノと思っていいはず。(細かい挙動は変わるけど、通常は問題にならないところのはず。)

// 最も省略した形
n -> n + 1

// 引数の型を書く
int n -> n + 1

// 引数は()で括る
(int n) -> n + 1

// 引数の()は0個のときは省略できない
() -> 12345

// 引数の()は2つ以上のときも省略できない
(x, y) -> x + y

// body は block にできる。この時は一文でもセミコロン要る。
(x, y) -> { return x + y; }

// block にしたらメソッドそのまま書く感じに
n -> {
    if (n % 15 == 0) return "FizzBuzz";
    if (n % 3 == 0) return "Fizz";
    if (n % 5 == 0) return "Buzz";
    return Integer.toString(n);
}

// void のときは空のblockにしとく
() -> {}

method reference / constructor reference

そのまま……メソッドコンストラクタの参照。

// コロン2つに続けてメソッド名
System.out::println

// コンストラクタはnewぽい
String::new

なんでこんなものが Lambda で出るかと言うと、Lambda と同じ感じで Functional Interface の実装として扱える。

// Lambda で Block を実装する
Arrays.asList(1, 2, 3, 4, 5).stream()
        .filter(n -> n % 2 == 0)
        .forEach(n -> System.out.println(n));

// method reference を Block にする
Arrays.asList(1, 2, 3, 4, 5).stream()
        .filter(n -> n % 2 == 0)
        .forEach(System.out::println);


引数の数と戻りの型をあわせれば良いだけなので、自分で作ったのでも。

// こんなのを作っといて
interface Hoge {
    Integer str2int(String str);
}

// Integerのコンストラクタに文字列渡す
Hoge hoge = Integer::new;
Integer actual = hoge.str2int("123");
assertThat(actual, is(123));

……下手な使い方されると困りそう。

IDE対応

試したいけどIDE無しでJava書くのなんて無理って人も、 NetBeans および IntelliJ IDEA では既に対応しています。IntelliJ IDEA だとプロジェクトの設定から選ぶだけ。NetBeans は知りません。

*1:とか書いてたら延期された……大丈夫じゃありませんでしたね(´・ω・`) http://twitter.com/kis/status/337950690896912385