1.8.1以降をキャッチアップするシリーズその3、引数無しfind/findAllの新規追加
Groovy 1.8.1以降で追加されたGDKメソッド(主にコレクション関係)を解説するシリーズ第3段、「引数無しfind/findAllの新規追加」です。
引数無しのfind()とfindAll()
Groovy 1.8.1では以下の2つのGDKメソッドが追加されています。
- public Object find()
- public Collection findAll()
find(),findAll()はもともと定義されていましたが、これらの引数無しバージョンです。
意味は、引数有りのfind(Closure) / findAll(Closure) のクロージャ引数にClosure.IDENTITYを与えて呼び出した場合と等価です。IDENTITYもClosureクラスに新規追加されたクロージャ定数です。名称はたぶん恒等関数(Identity function)から来ており、要は何も変化しない変換、引数そのままを返すようなクロージャです。Closure.IDENTITYは例えば以下のような感じで定義されています*1。
class Closure { .. static final Closure IDENTITY = { arg -> arg } // もしくは { it } ... }
ここで一旦、クロージャ引数のあるfind(Closure c),findAll(Closure c)の仕様をおさらいしておきましょう。これらの仕様は
- find(Closure c) :コレクションの要素eのうち、c.call(e)が真と判断される最初のものを返す
- findAll(Closure c) :コレクションの要素eのうち、c.call(e)が真と判断されるすべての要素からなるコレクションを返す
だったわけですが、引数無しバージョンの意味はそれぞれ
- find() :コレクションの要素eのうち、IDENTITY.call(e)が真と判断される最初のものを返す
- findAll() :コレクションの要素eのうち、IDENTITY.call(e)が真と判断されるすべての要素からなるコレクションを返す
となります。なお、find,findAllにおいて、「要素が真(条件を満す)かどうか」の判断は、Groovy Truthで判断されます。つまり、booleanであればtrue、数値であれば0以外、コレクションであれば空ではない、参照型であればnullではないような要素が真と判断されます。結果的に、引数無しfindは「非false、非0、非null、非空‥である最初の要素」、引数無しfindAllは「非false、非0、非null、非空…であるすべての要素」を返すことになります。
以下は例です。
assert [0,null,[],1,3,0,2,4].find() == 1 assert [0,null,[],1,3,0,2,4].findAll() == [1,3,2,4] // 上は以下と等価 assert [0,null,[],1,3,0,2,4].find(Closure.IDENTITY) == 1 assert [0,null,[],1,3,0,2,4].findAll(Closure.IDENTITY) == [1,3,2,4] // さらに言えば、以下と等価でもある。 assert [0,null,[],1,3,0,2,4].find{it} == 1 assert [0,null,[],1,3,0,2,4].findAll{it} == [1,3,2,4]
find系は次のfindResultsと合せて1回のエントリにするつもりだったのですが、思いのほか長くなったので続きます〜。