How can I convet MutableMap to vararg values: Pair?
How can I convet MutableMap<String, Any?> to vararg values: Pair<String, Any?>?
The following code is from "Kotlin for Android Developers", you can access it at https://github.com/antoniolg/Kotlin-for-Android-Developers
In order to insert a row data into CityForecastTable.NAME, I have to pass a vararg values by Source Code fun SQLiteDatabase.insert
CityForecastTable.NAME
vararg
fun SQLiteDatabase.insert
1: The author make a extension toVarargArray() to convert a MutableMap<String, Any?> to Pair<String, Any?>, I don't know whether there is a better way to do that. Do I need to use a extension function?
toVarargArray()
MutableMap<String, Any?>
Pair<String, Any?>
2: The author have to use the code it.value!! in Code C , I don't know if the code fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V?>> = map({ Pair(it.key, it.value) }).toTypedArray() is right?
it.value!!
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V?>> = map({ Pair(it.key, it.value) }).toTypedArray()
3: I don't know whether the app will crash when I insert a row data of which a column include null value.
import org.jetbrains.anko.db.*
class ForecastDb(private val forecastDbHelper: ForecastDbHelper = ForecastDbHelper.instance,
private val dataMapper: DbDataMapper = DbDataMapper()) : ForecastDataSource {
fun saveForecast(forecast: ForecastList) = forecastDbHelper.use {
//dataMapper.convertFromDomain(forecast) will return CityForecast object
with(dataMapper.convertFromDomain(forecast)) {
insert(CityForecastTable.NAME, *map.toVarargArray())
}
}
}
class CityForecast(val map: MutableMap<String, Any?>, val dailyForecast: List<DayForecast>) {
var _id: Long by map
var city: String by map
var country: String by map
constructor(id: Long, city: String, country: String, dailyForecast: List<DayForecast>)
: this(HashMap(), dailyForecast) {
this._id = id
this.city = city
this.country = country
}
}
Code C
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V>> =
map({ Pair(it.key, it.value!!) }).toTypedArray()
Source Code
fun SQLiteDatabase.insert(tableName: String, vararg values: Pair<String, Any?>): Long {
return insert(tableName, null, values.toContentValues())
}
Looking for an answer drawing from credible and/or official sources.
2 Answers
2
You have pretty much everything there
Use the asterisk * operator also known as spread operator to spread your array to vararg inside function.
*
vararg
https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs
Add ? to the value and you are ready to go
fun <K, V : Any> Map<K, V?>.toVarargArray() = map { it.key to it.value }.toTypedArray()
insert("", *mapOf("k" to "v").toVarargArray())
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V?>> = map({ Pair(it.key, it.value) }).toTypedArray()
I don't know whether the app will crash when I insert a row data of which a column include null value.
– HelloCW
Jul 23 at 3:09
No, you do not really need an extension function for that. It may make sense to have something in place if you are calling the insert-method (or any other which requires arrays instead of a Map) often. However depending on what you call more often, you may rather supply an extension function for the specific method with the Map as parameter instead.
insert
Map
Map
If you do not want to have the extension function you can call the following directly (if you aleady have a map):
*map.map { it.key to it.value }.toTypedArray()
I wonder why the author allows Any? on the CityForecast-class as values but then decides to use value!!. I would rather recommend either using Any, that way no null values are allowed or otherwise falling back to a default, e.g. value?:"". Note that if you use Any, you probably need to ensure that your data in the database is not containing any null-values (column created with NOT NULL constraint).
Any?
CityForecast
value!!
Any
null
value?:""
Any
null
NOT NULL
You really should try it out. If it crashes you get familiar on how to deal with errors. I assume that it crashes (or at least throws a NullPointerException somewhere ;-)) if you use null values in the map and keep the mentioned extension function as then the value!!-call will fail. And note: you can always come back here to ask new questions, if there is an issue you can't resolve or you do not find any good sources for it.
NullPointerException
null
value!!
Thanks! For 1, could you show me some code instead of
*map.toVarargArray() in insert(CityForecastTable.NAME, *map.toVarargArray()) ?– HelloCW
yesterday
*map.toVarargArray()
insert(CityForecastTable.NAME, *map.toVarargArray())
Basically you can just call what is written in the extension function. Note that I do not know the method signature of
insert, but I think the following will already suffice: insert(CityForecastTable.NAME, "k" to "v", "otherkey" to "othervalue", /*alternatively*/ Pair("k2", "v2"))– Roland
yesterday
insert
insert(CityForecastTable.NAME, "k" to "v", "otherkey" to "othervalue", /*alternatively*/ Pair("k2", "v2"))
Ok. I know the signature if it's the one you posted, but with the mobile writing some comments it just disappears ;-) so the mentioned code in the comment suffices already.
– Roland
yesterday
Thank! I hope to convet
MutableMap<String, Any?> to vararg values: Pair<String, Any?> as parameter of insert function. At present, I think that extension function fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V>> = map({ Pair(it.key, it.value!!) }).toTypedArray() is not good.– HelloCW
yesterday
MutableMap<String, Any?>
vararg values: Pair<String, Any?>
insert
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V>> = map({ Pair(it.key, it.value!!) }).toTypedArray()
Well, it's nearly ok. I don't trust the
it.value!!. Why shouldn't I be allowed to insert null-values (except the database column has NOT NULL declared). If you don't want to use the extension function, but you want to use the map, then you can still write: *map.map { it.key to it.value }.toTypedArray().– Roland
yesterday
it.value!!
null
NOT NULL
*map.map { it.key to it.value }.toTypedArray()
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thanks! Is the code
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V?>> = map({ Pair(it.key, it.value) }).toTypedArray()right?– HelloCW
Jul 23 at 3:09