Replacing stream collection in native Kotlin solution

I am currently using a Kotlin function to extract a map from a Json structure with key value pairs.

The JSON used to build the map contains a label and a value:

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

      

The "JSON tag" should be the key to the map and the value "value".

This is the code used to retrieve and convert JSON to a map using the Java 8 stream collect method.

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 -> })
}

      

How do you write the part with stream (). Going to idiomatic Kotlin? What alternatives do you need to replace

flow(). Collect()

in this particular case?

+3


source to share


3 answers


So you have a list of pairs and you want to convert it to a map? You can just replace .stream().collect(...)

with Kotlin toMap()

. From the Kotlin docs:

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

Returns a new map containing all key-value pairs from the given collection of pairs.



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

+3


source


I believe the call should work here toMap

, since you have an Iterable of pairs:



valuesNode.map { Pair(it.get("label")?.asText() ?: "", it.get("value")?.asText() ?: "") }.toMap()

      

+2


source


the associateBy method is similar to java Collectors#toMap

, so you can just do it in kotlin like below:

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


source







All Articles