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" и безопасный способ сделать это на карте:
- Проверьте, имеет ли карта данный ключ,
- И если да, получите значение этого ключа
Ответы
Ответ 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'