Rubyのブロック引数渡しをJavaでやると

Rubyではメソッドにブロックを渡すとクロージャ(Closure)を構築できます。
Enumerableクラスのdetectメソッドを例として見てみましょう。
ちなみにdetectはブロック内の条件式が初めて真となった際に配列の要素を返します。


array = (1..10).to_a

p array.detect {|e| e >= 5} →5を返す。

ちなみにJavaにこのクロージャの機構はありません。Java7で導入が検討されていたようですが、残念ながら見送りになりました。

とはいえ現状のJavaでも無名クラスを使うことで「クロージャっぽいこと」はできるのです。

まずクロージャ用interfaceを用意します。detectを再現するために戻り値をbooleanにします。


public interface ConditionalClosure {

boolean execute(T element);

}


※ここでは独自のクロージャinterfaceにしましたが、commons-collection15にもinterfaceが用意されています。commons-collection15が今のところ一番有名で汎用的でしょうね。

次にdetectメソッドを作ります。


public class ArrayUtil {

public static T detect(List list, ConditionalClosure closure) {
for (T element : list) {
if (closure.execute(element)) {
return element;
}
}
return null;
}
}


ConditionalClosure#executeが初めてtrueになったときの要素を返すという処理です。

では、実際にdetectしてみましょう。


public class DetectTest {
@Test
public void testDetect() {
List list = new ArrayList();
for (int i = 1; i <=10; i++) {
list.add(i);
}

int result = ArrayUtil.detect(list, new ConditionalClosure() {
public boolean execute(Integer element) {
return element >= 5;
}
});

assertEquals(5, result);
}
}


ArrayUtil#detectの第2引数にConditionalClosureを実装した無名クラスのインスタンスを渡します。あとは、executeメソッドに条件式を書くだけです。detectは条件式が初めて真となった際の配列の要素(つまり5)を返します。使う側はListをループで回すコードを書かずに、条件式だけ書けば合致する要素を抽出できることになります。

別に特別なことをしているわけではありません。知らず知らずにクロージャっぽいことをしている人もいると思いますよ。配列のソート時に無名なComparatorを実装することもよくあるでしょう。あれも同じようなことです。