Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

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?

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())
}
like image 696
HelloCW Avatar asked Jul 22 '18 01:07

HelloCW


2 Answers

You have pretty much everything there

Use the asterisk * operator also known as spread operator to spread your array to vararg inside function.

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())
like image 197
PolishCivil Avatar answered Oct 17 '22 17:10

PolishCivil


  1. 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.

    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()
    
  2. 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).

  3. 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.

like image 32
Roland Avatar answered Oct 17 '22 19:10

Roland