web-dev-qa-db-ja.com

groovy:マップ内のキーを安全に見つけてその値を返します

特定のマップで特定のキーを見つけたい。キーが見つかった場合、マップからそのキーの値を取得します。

これは私がこれまで管理してきたことです:

_def mymap = [name:"Gromit", likes:"cheese", id:1234]

def x = mymap.find{ it.key == "likes" }

if(x)
    println x.value
_

これは機能し、出力は予想どおり「チーズ」です。すばらしいですが、最後に_x.value_をやりたくないので、if(x)をやりたくありません。 xに何らかの方法で値を直接含めたい。

このようにxに値を直接取得することはできません。

_def mymap = [name:"Gromit", likes:"cheese", id:1234]

def x = mymap.find{ it.key == "likesZZZ" }.value

println x
_

この場合、検索クロージャーはnullであるため、Nullポインター例外が発生します。もちろん、上記のコードスニペットは_it.key == "likes"_の場合に機能しますが、マップ内でターゲットキーが常に見つかるかどうかはわかりません。

「Groovier」とは、マップ上でこれを行う安全な方法です。

  • マップに特定のキーがあるかどうかを確認し、
  • もしそうなら、このキーの値を取得
42
nonbeing
def mymap = [name:"Gromit", id:1234]
def x = mymap.find{ it.key == "likes" }?.value
if(x)
    println "x value: ${x}"

println x.getClass().name

?.はnullをチェックし、Groovyで例外を作成しません。キーが存在しない場合、結果はorg.codehaus.groovy.runtime.NullObject

20

マップを使用する全体のポイントは直接アクセスです。マップの値がGroovy -falseにならないことが確実にわかっている場合は、次のようにできます。

def mymap = [name:"Gromit", likes:"cheese", id:1234]
def key = "likes"

if(mymap[key]) {
    println mymap[key]
}

ただし、値が潜在的にGroovy -falseになる可能性がある場合は、以下を使用する必要があります。

if(mymap.containsKey(key)) {
    println mymap[key]
}

ただし、値がGroovy -falseにならない(または無視できる)場合、デフォルト値が必要な場合、最も簡単な解決策は次のとおりです。

def value = mymap[key] ?: "default"

これらの3つのソリューションはすべて、マップ全体でキーをスキャンしないため、例よりもはるかに高速です。直接キーアクセスをほぼ瞬時に行うHashMap(またはLinkedHashMap)設計を利用します。

56
OverZealous

一般的に、これはマップに含まれるものに依存します。 null値がある場合、物事はトリッキーになる可能性があり、containsKey(key)またはget(key, default)を使用して、要素が実際に存在することを検出する必要があります。多くの場合、コードはよりシンプルになり、デフォルト値を定義できます。

_def mymap = [name:"Gromit", likes:"cheese", id:1234]
def x1 = mymap.get('likes', '[nothing specified]')
println "x value: ${x}" }
_

containsKey()またはget()は、要素_mymap.find{ it.key == "likes" }_をチェックするクロージャーを設定するよりもはるかに高速であることに注意してください。クロージャーを使用するのは、そこでもっと複雑なことを実際に行う場合にのみ意味があります。あなたは例えばこれを行う:

_mymap.find{ // "it" is the default parameter
  if (it.key != "likes") return false
  println "x value: ${it.value}" 
  return true // stop searching
}
_

または、明示的なパラメーターを使用します。

_mymap.find{ key,value ->
  (key != "likes")  return false
  println "x value: ${value}" 
  return true // stop searching
}
_
2
Axel Heider

Null Pointer Exceptionが発生する理由は、2番目の例にキーlikesZZZがないためです。試してください:

def mymap = [name:"Gromit", likes:"cheese", id:1234]
def x = mymap.find{ it.key == "likes" }.value
if(x)
    println "x value: ${x}"
0