Подтвердить что ты не робот

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 Pointer. Конечно, приведенный выше фрагмент кода работает, когда it.key == "likes", но я не уверен, что всегда найду целевой ключ на карте.

Что такое "Groovier" и безопасный способ сделать это на карте:

  • Проверьте, имеет ли карта данный ключ,
  • И если да, получите значение этого ключа
4b9b3361

Ответ 1

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.

Ответ 2

Весь смысл использования Карт - прямой доступ. Если вы точно знаете, что значение на карте никогда не будет 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"

Все три этих решения значительно быстрее, чем ваши примеры, поскольку они не сканируют всю карту для ключей. Они используют дизайн HashMap (или LinkedHashMap), который обеспечивает непосредственный доступ к ключам почти мгновенно.

Ответ 3

В общем, это зависит от вашей карты. Если он имеет нулевые значения, все может стать сложным, и 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
}

Ответ 4

Причина, по которой вы получаете исключение Null Pointer, заключается в том, что в вашем втором примере нет ключа likeZZZ. Попробуйте:

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

Ответ 5

Карты Groovy можно использовать со свойством property, поэтому вы можете просто сделать:

def x = mymap.likes

Если ключ, который вы ищете ('likes.key'), содержит саму точку, то вы можете использовать синтаксис:

def x = mymap.'likes.key'