【问题标题】:What happened when the code HashMap(it) is run?运行代码 HashMap(it) 时发生了什么?
【发布时间】:2017-11-06 16:23:41
【问题描述】:

以下示例代码来自 Kotlin-for-Android-Developers https://github.com/antoniolg/Kotlin-for-Android-Developers/blob/master/app/src/main/java/com/antonioleiva/weatherapp/data/db/ForecastDb.kt

我无法完全理解代码DayForecast(HashMap(it))。 “它”是什么意思?

还有,当parseList { DayForecast(HashMap(it)) }被执行时发生了什么?

override fun requestForecastByZipCode(zipCode: Long, date: Long) = forecastDbHelper.use {

        val dailyRequest = "${DayForecastTable.CITY_ID} = ? AND ${DayForecastTable.DATE} >= ?"
        val dailyForecast = select(DayForecastTable.NAME)
                .whereSimple(dailyRequest, zipCode.toString(), date.toString())
                .parseList { DayForecast(HashMap(it)) }
}



class DayForecast(var map: MutableMap<String, Any?>) {
    var _id: Long by map
    var date: Long by map
    var description: String by map
    var high: Int by map
    var low: Int by map
    var iconUrl: String by map
    var cityId: Long by map

    constructor(date: Long, description: String, high: Int, low: Int, iconUrl: String, cityId: Long)
            : this(HashMap()) {
        this.date = date
        this.description = description
        this.high = high
        this.low = low
        this.iconUrl = iconUrl
        this.cityId = cityId
    }
}

已添加

在下面的示例代码中,我可以理解代码val doubled = ints.map {it * 2 }中的“it”,“it”是var ints的元素,比如10、20、30!

但是在代码val dailyForecast = select(DayForecastTable.NAME).whereSimple(dailyRequest, zipCode.toString(), date.toString()).parseList { DayForecast(HashMap(it)) }中,“它”是什么意思呢?

示例代码

 var  ints= listOf(10,20,30);

 val doubled = ints.map {it * 2 }


 fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
        val result = arrayListOf<R>()
        for (item in this)
            result.add(transform(item))
        return result
  }

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    正如 Lym Zoy 所说,it 是闭包的单个参数的隐式名称。

    如果您不熟悉 Kotlin 中的闭包和高阶函数,可以阅读 here 了解它们。采用闭包/函数/lambda 的函数基本上是在寻求一些帮助来完成它的工作。

    我喜欢使用sortedBy 作为一个很好的例子。 sortedBy 是 Kotlin 集合库中的一个函数,用于对集合进行排序,但为了使其工作,它需要每个项目的可比较属性。它解决这个问题的方法是它要求您(sortedBy 函数的用户)提供一个函数,该函数接受集合的一个成员并返回一个可比较的属性。例如,如果集合是 Person 对象的列表,如果您想按名字、姓氏或年龄排序,则可以提供 sortedBy 一个不同的闭包。

    这是一个简单的示例,您还可以找到 here ,它显示了 sortedBy 如何接受一个闭包参数,该参数接受一个成员并返回一个可比较的属性,sortedBy 可以使用该属性对收藏。在第一种情况下,闭包/函数返回成员的年龄,在第二种情况下,闭包返回 lastName(使用隐式形式),两者都是 Comparable、Int 和 String。

    data class Person(val firstName: String, val lastName: String, val age: Int)
    
    fun main(args: Array<String>) {
    
      val people = listOf( Person("Jane", "Jones", 27), Person("Johm", "Smith", 22), Person("John", "Jones", 29))
      val byAge = people.sortedBy { person -> person.age  }  // explicit argument: person is a memeber of the List of Persons
      val byLastName = people.sortedBy { it.lastName } // implict argument: "it" is also a member of the List of Persons 
      println(people)
      println(byAge)
      println(byLastName)
    

    }

    回到您的具体问题的细节。

    在您的问题中,找到 here 的 parseList 函数定义如下:

    fun <T : Any> SelectQueryBuilder.parseList(parser: (Map<String, Any?>) -> T): List<T> =
            parseList(object : MapRowParser<T> {
                override fun parseRow(columns: Map<String, Any?>): T = parser(columns)
            })
    

    这是一个接受一个闭包的函数,该闭包需要一个 Map&lt;String, Any?&gt; 类型的参数

    所以在你的问题中显示的电话中:

    .parseList { DayForecast(HashMap(it)) }
    

    { DayForecast(HashMap(it)) } 是预期传递给 parseList 的闭包,
    较长的形式 { arg -&gt; DayForecast(HashMap(arg) } 也可以使用,但较短的形式 { DayForecast(HashMap(it)) } 是更惯用的形式,其中使用 it 作为参数允许您跳过 arg -&gt; 部分。

    所以在这种情况下,itparseList 函数提供的 Map 对象。 it 引用的对象然后作为唯一参数传递给 HashMap 构造函数(这并不奇怪需要一个 Map),该构造的结果然后被传递给 DayForecast 的构造函数

    【讨论】:

    • 谢谢!你的意思是 HashMap(it) 将闭包转换为 Map) ?
    • 不,我的意思是闭包/函数采用 parseList 提供给它的 Map 并将 DayForecast 返回给 parseList。它通过将函数 { DayForecast(HashMap(it)) } 中的 Map 对象作为“it”传递来做到这一点
    • 从您的评论看来,您似乎需要更多关于整个闭包、高阶函数概念的背景知识。我添加了一点背景、示例和一些链接。
    • 谢谢!如果“所以在这种情况下它是 parseList 函数提供的 Map 对象”,为什么我不能使用 .parseList { DayForecast(it) } 而不是 .parseList { DayForecast(HashMap(it)) }
    • 我认为这是另一个问题。您必须查看 DayForecast 类并查看,但 Kotlin 中的 Map 是一个接口,而 HashMap 是一个具体类,所以我的猜测是 DayForecast 期待一个实际的 HashMap,而不仅仅是实现 Map 接口的东西。
    【解决方案2】:

    it 是单个参数的隐含名称。检查文档here

    【讨论】:

    • 谢谢,但是单个参数的隐式名称应该是{},比如ints.map { it * 2 },在我的代码中是HashMap(it)
    • map 的签名是 map(transform: (T) -&gt; R)。当使用 map { it * 2 } 时,这意味着参数transform 这里是(it)-&gt;{ it * 2 }it 是单个参数 T 的名称。
    猜你喜欢
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多