I see that #filter
is defined on Map
, but I am not able to figure out how to use it. Anyone care to share an example?
I have a deeply nested TreeMap instance (TreeMap<String, Map<String, Map<*, *>>>
) and I want to filter/find
the first (which is the only in the domain) top-level key that has a certain characteristics associated with something deeper in the value.
Here's how the data looks like:
{
"i1": {
"aliases": {}
},
"i2": {
"aliases": {}
},
"i3": {
"aliases": {}
},
"i4": {
"aliases": {
"alias-im-looking-for": {}
}
}
}
I have this following non-functional code which solves it right now:
val indexToAliasMappingType = LinkedTreeMap<String, Map<String, Map<*, *>>>()
val indexToAliasMappings = Gson().fromJson(response.jsonString, indexToAliasMappingType.javaClass)
var currentIndexName = ""
for ((index, aliasMappings) in indexToAliasMappings) {
val hasCurrentAlias = aliasMappings.get("aliases")?.containsKey(alias)
if (hasCurrentAlias != null && hasCurrentAlias) {
currentIndexName = index
}
}
return currentIndexName
You cannot invoke firstOrNull
on the map itself, but you can invoke it on its entries
set:
val currentIndexName = indexToAliasMappings.entries.firstOrNull {
it.value["aliases"]?.containsKey(alias) == true
}?.key
firstOrNull
iterates through map entries and stops on a first entry matching the predicate. No intermediate map allocations as in the variant with filter
or filterValues
are required here.
.filter
's lambda returns a boolean for each entry in the map. If that boolean evaluates to true
, that entry is part of the returned collection. If that boolean evaluates to false
, that entry is filtered out.
val indexToAliasMapping = linkedMapOf(
"i1" to mapOf(
"aliases" to mapOf<Any, Any>()
),
"i2" to mapOf(
"aliases" to mapOf<Any, Any>()
),
"i3" to mapOf(
"aliases" to mapOf<Any, Any>()
),
"i4" to mapOf(
"aliases" to mapOf(
"aliases-im-looking-for" to "my-alias"
)
)
)
// If you only need one, you could also use .first instead of .filter, which
// will give you a Pair<String, Map<String, Map<*, *>>> instead of a List
val allWithNonEmptyAliases: Map<String, Map<String, Map<*, *>>> = indexToAliasMapping.filter {
it.value["aliases"]?.containsKey(alias) ?: false
}
// We use .toList() so you can get the first element (Map doesn't allow you to retrieve by index)
return allWithNonEmptyAliases.toList().first().first
Looks like what you need is the key part of the first entry that matches your criteria. Something like this (single line intentional) should help:
val currentIndexName = indexToAliasMappings.filterValues { it["aliases"]?.containsKey(alias) ?: false }.keys.firstOrNull() ?: ""
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With