How do I convert map content


#1

Sorry, this really might sound like a newbie question: what is an elegant and type safe solution to transform the content of a map?

Suppose I have a Java class with the following signature that I want to use:
public Map parse(String content)
The method is annotated as @NotNull. The task shall be: wrap all (k,v) of that map that are of type string into a list of ConfigEntry objects.

Here are the options that I can think of:

  • map to ConfigEntry objects (or null) and then filter all nulls
  • filter everything that is not String and then map to ConfigEntry objects


Here’s what I am currently doing in Kotlin:

 
val r =  m.entrySet().map {
    val (k, v) = it  // not nice but otherwise error: it.key could change
    if (k is String && v is String) {
        ConfigEntry(k, v)
    } else {
        null
    }
}.filter { it != null }

Problem with this approach is that r is now of type List<ConfigEntry?> but expected is List<ConfigEntry>. I could cast but that doesn't appar to be elegant. The second approach has similar problems. After a filter { it.key is String && it.value is String } operation, the type of the collection is something like List<Map.Entry<Any?, Any?>> even thought there are only strings in the resulting collection.

flatMap doesn’t seem to help, either:

 
val r = m.entrySet().flatMap {
  val (k, v) = it
  if (k is String && v is String) {
  Optional.of(ConfigEntry(k, v))
  } else {
  Optional.empty()
  }
}

So, what is the way to go here?


#2

How about

 
val r =  m.entrySet().map {
    val (k, v) = it  // not nice but otherwise error: it.key could change
    if (k is String && v is String) {
        ConfigEntry(k, v)
    } else {
        null
    }
}.filter { it != null }.map { it!!}

#3

Hi, There is filterNotNull() function in stdlib:

val r: List<ConfigEntry> =  m.entrySet().map {   val (k, v) = it   if (k is String && v is String) {   ConfigEntry(k, v)   } else {   null   } }.filterNotNull()