【问题标题】:How can I convet MutableMap<String, Any?> to vararg values: Pair<String, Any?>?如何将 MutableMap<String, Any?> 转换为可变参数值:Pair<String, Any?>?
【发布时间】:2018-12-29 21:10:54
【问题描述】:

以下代码来自“Kotlin for Android Developers”,您可以在https://github.com/antoniolg/Kotlin-for-Android-Developers访问它

为了在CityForecastTable.NAME 中插入一行数据,我必须通过源代码 fun SQLiteDatabase.insert 传递一个vararg

1:作者做了一个扩展toVarargArray()MutableMap&lt;String, Any?&gt;转换为Pair&lt;String, Any?&gt;,不知道有没有更好的办法。我需要使用扩展功能吗?

2:作者必须在Code C中使用代码it.value!!,不知道代码fun &lt;K, V : Any&gt; Map&lt;K, V?&gt;.toVarargArray(): Array&lt;out Pair&lt;K, V?&gt;&gt; = map({ Pair(it.key, it.value) }).toTypedArray()对不对?

3:我不知道当我插入一个列包含空值的行数据时应用是否会崩溃。

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
    }
}

代码 C

fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V>> =
        map({ Pair(it.key, it.value!!) }).toTypedArray()

源代码

fun SQLiteDatabase.insert(tableName: String, vararg values: Pair<String, Any?>): Long {
    return insert(tableName, null, values.toContentValues())
}

【问题讨论】:

  • 应用是否会崩溃不是很容易测试吗?

标签: android kotlin anko


【解决方案1】:

你几乎什么都有

使用星号 * 运算符(也称为扩展运算符)将您的数组传播到函数内部的 vararg

https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs

添加?到价值,你准备好了

fun <K, V : Any> Map<K, V?>.toVarargArray() = map { it.key to it.value }.toTypedArray()

    insert("", *mapOf("k" to "v").toVarargArray())

【讨论】:

  • 谢谢!代码fun &lt;K, V : Any&gt; Map&lt;K, V?&gt;.toVarargArray(): Array&lt;out Pair&lt;K, V?&gt;&gt; = map({ Pair(it.key, it.value) }).toTypedArray()对吗?
  • 不知道当我插入一行数据的列包含空值时应用会不会崩溃。
  • 谢谢!如果V? 为空以在fun &lt;K, V : Any&gt; Map&lt;K, V?&gt;.toVarargArray() = map { it.key to it.value }.toTypedArray() 调用it.value,代码会崩溃吗?
【解决方案2】:
  1. 不,您实际上并不需要扩展功能。如果您经常调用insert-方法(或任何其他需要数组而不是Map)的方法,那么准备好一些东西可能是有意义的。但是,根据您更频繁地调用的内容,您可能宁愿为特定方法提供扩展函数,并将 Map 作为参数。

    如果你不想拥有扩展功能,你可以直接调用以下(如果你已经有地图):

    *map.map { it.key to it.value }.toTypedArray()
    
  2. 我想知道为什么作者允许CityForecast-class 上的Any? 作为值,但随后决定使用value!!。我宁愿推荐使用Any,这样就不允许使用null 值,或者以其他方式回退到默认值,例如value?:""。请注意,如果您使用Any,您可能需要确保数据库中的数据不包含任何null-值(使用NOT NULL 约束创建的列)。

  3. 您真的应该尝试一下。如果它崩溃了,你就会熟悉如何处理错误。我假设如果您在地图中使用null 值并保留提到的扩展功能,那么它会崩溃(或至少在某处抛出NullPointerException ;-))然后value!!-调用将失败。请注意:如果有您无法解决的问题或找不到任何好的来源,您可以随时回到这里提出新问题。

【讨论】:

  • 谢谢!对于 1,你能告诉我一些代码而不是 insert(CityForecastTable.NAME, *map.toVarargArray()) 中的 *map.toVarargArray() 吗?
  • 基本上你可以调用扩展函数中写的内容。请注意,我不知道insert 的方法签名,但我认为以下内容已经足够了:insert(CityForecastTable.NAME, "k" to "v", "otherkey" to "othervalue", /*alternatively*/ Pair("k2", "v2"))
  • 好的。我知道签名是否是您发布的签名,但是随着手机编写一些 cmets,它就会消失 ;-) 所以评论中提到的代码已经足够了。
  • 谢谢!我希望将MutableMap&lt;String, Any?&gt; 转换为vararg values: Pair&lt;String, Any?&gt; 作为insert 函数的参数。目前觉得扩展功能fun &lt;K, V : Any&gt; Map&lt;K, V?&gt;.toVarargArray(): Array&lt;out Pair&lt;K, V&gt;&gt; = map({ Pair(it.key, it.value!!) }).toTypedArray()不好。
  • 嗯,几乎没问题。我不相信it.value!!。为什么不允许我插入null-values(除了数据库列声明了NOT NULL)。如果你不想使用扩展功能,但又想使用地图,那么你仍然可以写:*map.map { it.key to it.value }.toTypedArray()
猜你喜欢
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 2022-01-02
  • 2011-03-08
相关资源
最近更新 更多