如何在Kotlin的Map实例上使用`filter`?

时间:2016-11-10 17:32:10

标签: java functional-programming gson kotlin

我看到Map上定义#filter,但我无法弄清楚如何使用它。有人愿意分享一个例子吗?

我有一个深度嵌套的TreeMap实例(TreeMap<String, Map<String, Map<*, *>>>),我想filter/find第一个(在域中唯一的)顶级键,它具有与更深层次相关的某些特征在价值中。

以下是数据的外观:

{
  "i1": {
    "aliases": {}
  },
  "i2": {
    "aliases": {}
  },
  "i3": {
    "aliases": {}
  },
  "i4": {
    "aliases": {
      "alias-im-looking-for": {}
    }
  }
}

我有以下非功能性代码,现在就解决了这个问题:

val indexToAliasMappingType = LinkedTreeMap<String, Map<String, Map<*, *>>>()
val indexToAliasMappings = Gson().fromJson(response.jsonString, indexToAliasMappingType.javaClass)

var currentIndexName = ""
for ((index, aliasMappings) in indexToAliasMappings) {
    val hasCurrentAlias = aliasMappings.get("aliases")?.containsKey(alias)
    if (hasCurrentAlias != null && hasCurrentAlias) {
        currentIndexName = index
    }
}

return currentIndexName

3 个答案:

答案 0 :(得分:5)

看起来您需要的是第一个符合条件的条目的关键部分。这样的事情(单线故意)应该有所帮助:

val currentIndexName = indexToAliasMappings.filterValues { it["aliases"]?.containsKey(alias) ?: false }.keys.firstOrNull() ?: ""

答案 1 :(得分:3)

您无法在地图上调用firstOrNull,但您可以在其entries集上调用它:

 val currentIndexName = indexToAliasMappings.entries.firstOrNull {
     it.value["aliases"]?.containsKey(alias) == true
 }?.key

firstOrNull遍历映射条目并在与谓词匹配的第一个条目上停止。此处不需要具有filterfilterValues的变体中的中间地图分配。

答案 2 :(得分:1)

.filter的lambda为地图中的每个条目返回一个布尔值。如果该布尔值计算为true,则该条目是返回集合的一部分。如果该布尔值为false,则该条目将被过滤掉。

val indexToAliasMapping = linkedMapOf(
    "i1" to mapOf(
        "aliases" to mapOf<Any, Any>()
    ),
    "i2" to mapOf(
        "aliases" to mapOf<Any, Any>()
    ),
    "i3" to mapOf(
        "aliases" to mapOf<Any, Any>()
    ),
    "i4" to mapOf(
        "aliases" to mapOf(
            "aliases-im-looking-for" to "my-alias"
        )
    )
)
// If you only need one, you could also use .first instead of .filter, which
// will give you a Pair<String, Map<String, Map<*, *>>> instead of a List
val allWithNonEmptyAliases: Map<String, Map<String, Map<*, *>>> = indexToAliasMapping.filter {
    it.value["aliases"]?.containsKey(alias) ?: false
}

// We use .toList() so you can get the first element (Map doesn't allow you to retrieve by index)
return allWithNonEmptyAliases.toList().first().first