Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
721 views
in Technique[技术] by (71.8m points)

kotlin - What happened when the code HashMap(it) is run?

The following sample code is from Kotlin-for-Android-Developers at https://github.com/antoniolg/Kotlin-for-Android-Developers/blob/master/app/src/main/java/com/antonioleiva/weatherapp/data/db/ForecastDb.kt

I can't understand completely the code DayForecast(HashMap(it)). what does "it" mean?

And more, what happend when the parseList { DayForecast(HashMap(it)) } is executed ?

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

Added

In the following Sample Code, I can understand "it" in the code val doubled = ints.map {it * 2 }, "it" is the element of var ints, such as 10, 20, 30 !

But in the code val dailyForecast = select(DayForecastTable.NAME).whereSimple(dailyRequest, zipCode.toString(), date.toString()).parseList { DayForecast(HashMap(it)) }, what does "it" mean ?

Sample Code

 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
  }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As Lym Zoy says it is the implicit name of the single argument to a closure.

If you are not familiar with closures and higher order functions in Kotlin, you can read about them here . A function that take a closure/function/lambda, is one that is basically asking for some help to do it's job.

I like using sortedBy as a good example. sortedBy is a function in the Kotlin collections library that will sort a collection, but in order for it to work it needs a comparable attribute for each item. The way it solves this is it asks you, the user of the sortedBy function, to provide a function that takes a member of the collection and returns a comparable attribute. For example if the collection was a list of Person objects, you could provide sortedBy a different closure if you wanted to sort by firstName, lastName or age.

Here is a quick example which you can also find here , which shows how sortedBy can take a closure argument which takes a member and returns a comparable attribute which sortedBy can use to rank the various members of the collection. In the first case the closure/function returns the age of the member and in the second case the closure returns the lastName (using the implicit form), both of which are Comparable, an Int and a 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)

}

Getting back to the detail of your specific question.

In your question the parseList function found here is defined as such:

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

This is a function that takes a closure that expects one argument of type Map<String, Any?>

So in the call shown in your question:

.parseList { DayForecast(HashMap(it)) }

where { DayForecast(HashMap(it)) } is the closure expected to be passed to parseList,
the longer form { arg -> DayForecast(HashMap(arg) } could have been used as well but the short form { DayForecast(HashMap(it)) } is the more idiomatic form where using it as the argument allows you to skip the arg -> part.

So in this case it is a Map object provided by the parseList function. The object referred to by it is then passed as the lone argument to a HashMap constructor (which not surprisingly expects a Map), the result of that construction, is then being passed to the constructor of DayForecast


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...