Groovy2.0でListに追加されたwithDefault、withEagerDefault、withLazyDefault

withDefaultはwithLazyDefaultのエイリアスなので機能的にはwithEagerDefault、withLazyDefaultが追加されました。今までmapには似たようなのがありましたが、今回Listにも追加されました。

それぞれ要素を取得した際の要素のパディング方法や、nullの扱いが若干違います。

まずwithLazyDefaultから。要素を取得したタイミングで初期化されnullの要素が特別な意味(初期化対象)を持っています。

def items = [1, 2].withLazyDefault { it * it }

assert items == [1, 2]

assert items[4] == 16
// 4を取ると間の要素をnullでパディング
assert items == [1, 2, null, null, 16]

assert items[3] == 9
// パディングされたnullの要素を取得するとそのタイミングで初期化されている
assert items == [1, 2, null, 9, 16]

// 自分でnullを入れてみる
items[1] = null
// 自分で入れたnullでも取得するとそのタイミングで初期化される
assert items[1] == 1
assert items == [1, 1, null, 9, 16]

次にwithEagerDefault。先ほどと違いパディングする際にその間の値も初期化されるのと、nullがnullとして扱われる点がEagerと異なります。

def items = [1, 2].withEagerDefault { it * it }

assert items == [1, 2]

assert items[4] == 16
// 4を取ると間の要素もあわせて初期化される
assert items == [1, 2, 4, 9, 16]

// 自分でnullを入れてみる
items[1] = null
// 自分で入れたnullはnullとして扱われる
// withLazyDefaultと違いnullを取得する際にその要素が初期化されたりしない
assert items[1] == null
assert items == [1, null, 4, 9, 16]