Actualmente estoy usando una función Kotlin para extraer un mapa de una estructura Json con pares de valores clave.

El JSON utilizado para construir el mapa contiene una etiqueta y un valor:

"values": [
{
  "label": "Email",
  "value": "email"
},
{
  "label": "Social media",
  "value": "socialMedia"
},
{
  "label": "Word of mouth",
  "value": "wordOfMouth"
},
{
  "label": "Newspaper",
  "value": "newspaper"
}
],

La "etiqueta" JSON debe convertirse en la clave del mapa y el "valor" en su valor.

Este es el código utilizado para extraer y convertir el JSON en un mapa utilizando el método de recopilación de flujo de Java 8.

fun extractValue(jsonNode: JsonNode?): Map<String, String> {
    val valuesNode = jsonNode?.get("values") ?: mapper.createArrayNode()
    return valuesNode.map { Pair(it.get("label")?.asText() ?: "", it.get("value")?.asText() ?: "") }
            .stream().collect({ HashMap<String, String>()}, { m, p -> m.put(p.first, p.second) } , { m, p -> })
}

¿Cómo se escribe la parte con stream (). Collect en Kotlin idiomático? ¿Qué alternativas tienes que reemplazar?

stream (). collect ()

En este caso especifico?

3
gil.fernandes 26 jun. 2017 a las 00:03

3 respuestas

La mejor respuesta

¿Entonces tienes una lista de pares y quieres convertirla en un mapa? Simplemente puede reemplazar su .stream().collect(...) con el toMap() de Kotlin. De los documentos de Kotlin:

fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V>

Devuelve un nuevo mapa que contiene todos los pares clave-valor de la colección de pares dada.

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/to-map.html

3
Sam 26 jun. 2017 a las 06:53

El método AssociateBy es como java { {X0}}, así que simplemente puedes hacerlo en kotlin de la siguiente manera:

fun extractValue(jsonNode: JsonNode?): Map<String, String> {
    //                              key mapping  ---v
    return jsonNode?.get("values")?.associateBy({ it.get("label")?.asText()?:"" }){
        it.get("value")?.asText() ?: "" // value mapping
    } ?: emptyMap()
    //   ^--- default value is an empty map
}
2
holi-java 25 jun. 2017 a las 22:39

Creo que un toMap la llamada debería funcionar aquí, ya que tiene un Iterable de pares:

valuesNode.map { Pair(it.get("label")?.asText() ?: "", it.get("value")?.asText() ?: "") }.toMap()
2
zsmb13 25 jun. 2017 a las 21:19