GroovyのクロージャとJava8の関数型インタフェースとの密な関係
今回は少し目先を変えて、Java 8で追加された関数型インタフェースを引数に取る新しいAPIを、Groovyから使うにはどうしたらよいか、という話です。
中野靖治のGroovy活用術 第8回
- 2016年04月21日公開
GroovyのクロージャとJava 8の関数型インタフェースとの密な関係
はじめに
こんにちは。NTTソフトウェアの中野です。
今回は少し目先を変えて、Java 8で追加された関数型インタフェースを引数に取る新しいAPIを、Groovyから使うにはどうしたらよいか、という話です。
関数型インタフェースとラムダ式
Java 8では、次の条件を満たす関数型インタフェースと呼ばれる概念が導入されました。
- 抽象メソッドが1つ定義されているインタフェース
- そのほかにstaticメソッドや、defaultメソッドはあってもなくてもよい
Java 8では関数型インタフェースを利用した便利なAPIがたくさん追加されました。
// 関数型インタフェース Predicatep = new Predicate () { @Override boolean test(Number num) { return num % 2 == 0; } } List evenNums = [1, 2, 3, 4, 5].stream().filter(p).collect(Collectors.toList()); System.out.println(evenNums); //=> [2, 4]
関数型インタフェースはラムダ式という新しいシンタックスでシンプルに記述できます。
ListevenNums = [1, 2, 3, 4, 5] .stream() .filter(num -> num % 2 == 0) // ラムダ式で条件をインライン指定できる! .collect(Collectors.toList()); System.out.println(evenNums); //=> [2, 4]
Groovyとラムダ式
GroovyはJavaの上位互換性を保つことを目標としています。実際、Java 7までのシンタックスとは高い互換性を持っていました(※)。しかし、残念ながら、Java 8のラムダ式には、Groovyのクロージャとは互換性のない文法が採用されました。Java 8のラムダ式を用いたJavaコードをGroovyコードとして実行することは、残念ながら現時点はできません。
※ 配列やdo-whileなどの一部のシンタックスについては以前から互換性がありません。
空気の読めるクロージャ
実は、Groovyのクロージャは、関数型インタフェースが要求される文脈で使用すれば、そのまま関数型インタフェースのインスタンスとして解釈されるようになっています。このため、Stream APIなどのラムダ式を前提としたAPIであっても、明示的な変換を必要とせずにそのままクロージャを渡して違和感なく使用することができます。
たとえば、先ほどのJavaのサンプルと同じ処理であれば、Groovyではこのように書けます。
import java.util.stream.*
ListevenNums = [1, 2, 3, 4, 5] .stream() .filter { num -> num % 2 == 0 } // Groovyクロージャをそのまま渡せる! .collect(Collectors.toList()) //.collect() // Groovyのcollectメソッドを使うこともできる assert evenNums == [2, 4]
もちろん、単に同じことをGroovyで最短で書こうと思えば、Stream APIを使わなくても
ListevenNums = [1, 2, 3, 4, 5].findAll { it % 2 == 0 } assert evenNums == [2, 4]
と書けますが、ここで言いたいのは「Groovyのコレクション操作は便利!」という話ではありません。
ここでのポイントは、Stream APIに限らず 関数型インタフェースを引数にとるAPIがある場合に、GroovyからそのAPIを使うには、ラムダ式の代わりに単にクロージャを渡せばいい ということです。
おわりに
今後、Java 8のラムダ式の記法をGroovy側が取り込むのか、それとも現行のクロージャを使うことで特に問題ないため、シンタックスの互換性には目をつぶるのか。どちらにしろ、実用的にはそれほど困ったことにはならないので、個人的にはこのままでもよいと思っています。

JVM上で動作する動的型付け言語であるGroovyと、Groovyで記述するWebアプリケーションフレームワークのGrailsを社内外へ推進するために日々奮闘している。 Groovyスクリプトの起動時間を短縮するGroovyServや、GroovyスクリプトでのExcel操作を劇的に楽にするGExcelAPIなどのOSSを業務/プライベートで開発、 一般に公開。Groovy/Grails/GradleなどのOSSへのバグフィックスや機能パッチの提供などにも積極的に貢献している。 また、国内外(JJUG CCC、Java Day Tokyo, Gr8conf EUなど)での講演や書籍執筆などでも活動中。 著書に『プログラミングGroovy』(技術評論社/共著)がある。自他共に認めるビール党。