I need a function which will cast Map
to Map<String, List<Int>>
Currently I use unsafe "as" but I receive a fair warning about it. I want to fix it.
For list part I was able to implement function
inline fun <reified T : Any> List<*>.checkItemsAre(): List<T> {
return this.filterIsInstance<T>().takeIf { it.size == this.size }
?: throw IllegalArgumentException("blablabla")
}
But I can't fund analog for map.
How can I fix it ?
If you are looking for something similar to the checkItemsAre
for List
s that you showed, you can write such a method for Map
s.
inline fun <reified K : Any, reified V: Any> Map<*, *>.checkKeyValuesAre() =
entries.associate {
Pair(
(it.key as? K) ?: throw IllegalArgumentException(),
(it.value as? V) ?: throw IllegalArgumentException()
)
}
Just like checkItemsAre
, this creates a new Map
if all the keys are of type K
and all the values are of type V
.
However, this wouldn't completely check nested generics like Map<String, List<Int>>
. If you want to handle that, you would have to add special cases for List
, e.g.
return if (typeOf<V>().classifier == List::class) {
val listElemType = typeOf<V>().arguments[0].type?.classifier as KClass<*>
entries.associate {
Pair(
(it.key as? K) ?: throw IllegalArgumentException(),
(it.value as List<*>).checkItemsAre(listElemType)
)
}
} else {
// the code in the first code snippet...
}
fun <T : Any> List<*>.checkItemsAre(clazz: KClass<T>): List<T> {
return this.filterIsInstance(clazz.java).takeIf { it.size == this.size }
?: throw IllegalArgumentException()
}
If you are only going to handle maps with values of type List
, I would just assume the map's values are lists:
inline fun <reified K : Any, reified E: Any> Map<*, *>. checkKeyAndListValuesAre() =
entries.associate {
Pair(
(it.key as? K) ?: throw IllegalArgumentException(),
(it.value as List<*>).checkItemsAre<E>()
)
}