LoginSignup
5
5

More than 5 years have passed since last update.

[Groovy]MapをPHPの連想配列のようにお気楽に扱えるようにする

Posted at

やりたいこと

PHPだと、以下のように連想配列を利用できます。

<?php
$array = array();
$array["a"]["sub-1"] = 111;
$array["a"]["sub-2"] = 222;
$array["b"]["sub-1"] = 333;
print_r($array);

実行結果は、

Array
(
    [a] => Array
        (
            [sub-1] => 111
            [sub-2] => 222
        )

    [b] => Array
        (
            [sub-1] => 333
        )

)

一目瞭然ですね。素敵です。
こんな感じでサクサク連想配列をGroovyでも使いたいですね。
Groovyだと連想配列に該当するのはMapになります。
実際にやってみましょう。

def map = [:] // Mapインスタンスの生成
map ["a"]["sub-1"] = 111

しかし、コレを実行するとjava.lang.NullPointerException: Cannot set property 'sub-1' on null objectという例外が発生します。
というのも、GroovyのMapの動作として、まずmap["a"]から値を取得して、その値のsub-1というプロパティに111を代入する、という流れになっているので、そもそもmap["a"]は何もないのでnullを返すため、nullのプロパティに値を突っ込もうとしてもダメだよ!と怒られているんですね。

assert map["a"] == null

解決方法

GroovyのMapには、「該当するキーがなければ、そのキーと指定したデフォルト値を使って新しい値をMapに突っ込む」という便利メソッドwithDefaultがあります。
鋭い人ならこの時点でピンと来るかもしれません。このwithDefaultを使って、キーが存在しない場合には、そのキーをキーとして 新しいMap を突っ込んであげれば上記の問題を解決できます。

日本語だけだと何がなんだかわからないですね。実際のソースを見てみれば一目瞭然です。

def map = [:].withDefault{[:]}
map["a"]["sub-1"] = 111
map["a"]["sub-2"] = 222
map["b"]["sub-1"] = 333

assert [
  "a":[
    "sub-1":111,
    "sub-2":222
  ],
  "b":[
    "sub-1":333
  ]
] == map

最初の[:]でMapインスタンスを生成するタイミングで、.withDefault{[:]}を使って、キーが存在しない場合には空の新しいMapを返すように宣言しています。
これで、GroovyでもPHPの連想配列のように、よりお気楽にMapが利用できるようになります。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5