我有一张收藏地图。我需要从中获取 id 列表..
val m1 = mapOf("id" to 1, "name" to "Alice")
val m2 = mapOf("id" to 2, "name" to "Bob")
val m3 = mapOf("id" to 3, "name" to "Tom")
val nameList = listOf(m1, m2, m3)
结果应该是[1, 2, 3]
答案 0 :(得分:4)
假设您想要根据示例的列表,而不是根据标题的地图,我会这样做:
val result = nameList.map {
it.getValue("id").also { id ->
require(id is Int) { "id must be an Int" }
} as Int
}
这样做的好处是可以干净地处理以下错误:
id
键:NoSuchElementException: Key id is missing in the map
id
值不是 Int
:IllegalArgumentException: id must be an Int
答案 1 :(得分:3)
首先,我相信如果可以的话,应该使用类而不是映射来存储像这样的异构数据。因此,您可以使用:
,而不是您的地图data class Person(val id: Int, val name: String)
val m1 = Person(id = 1, name = "Alice")
val m2 = Person(id = 2, name = "Bob")
val m3 = Person(id = 3, name = "Tom")
val list = listOf(m1, m2, m3)
val idsList = list.map { it.id } // no error handling required, rely on the type system
现在,如果您真的想使用这样的地图,您有多种选择。
如果您确定 id
键将存在且其值为 Int
,您可以使用以下内容:
nameList.map { it["id"] as Int }
如果 NullPointerException
不存在于其中一张地图中或 id
,如果它不是 ClassCastException
,这将失败。
通常,您应该确保您的地图在创建时与您的合同匹配,而不是在访问此类信息时。 但是如果你因为某种原因需要在这里处理错误,你可以使用下面的代替:
Int
nameList.map {
(it.getValue("id") as? Int) ?: error("'id' is not an Int")
}
因 getValue
缺少键而失败,而 NoSuchElementException
调用因 error()
而失败。您还可以使用 IllegalStateException
或 throw
使用其他类型的异常。
如果您只想忽略没有有效整数 require()
的条目,您可以使用以下内容:
id
如果您想忽略没有 nameList.mapNotNull { it["id"] as? Int }
的条目,但在那些具有非整数 id 的条目上失败,您可以使用:
id
这最后两个示例依赖于 nameList.mapNotNull { map ->
map["id"]?.let { id ->
(id as? Int) ?: error("'id' is not an Int")
}
}
,如果元素的映射值为 mapNotNull
,它将过滤掉元素。