您以前使用过默认地图或默认字典吗?如果你对Python有所了解,你可能会在某些时候看到它的实际效果。Kotlin还附带了一个类似的工具,我想在这篇小文章中展示。
您可以在此处找到Python文档和一些示例,但基本用例显示在以下代码段中:
它也可以与其他类型一起使用,并确保在运行代码时不会得到它。相反,它为未知键提供了一个默认值,这对于分组和计算算法非常有用,如下所示:
在这篇文章中,我想向您展示Kotlin如何处理地图的默认值以及其他替代方案。
一个简单的问题
假设我们想要编写一个泛型函数,该函数接受一个集合并返回一个映射,该映射包含与其出现次数相关的原始集合中的元素:
虽然在科特林(当然)有一种自然而简单的功能式方法,但我们首先要考虑一些迭代方法。让我们从以下开始吧。
没有默认值的迭代解决方案
funcountOccurrences(values:Collection):Map{
valcountMap=mutableMapOf()
for(einvalues) {
valcurrent=countMap[e]
if(current==null)countMap[e]=1
elsecountMap[e]=current+1
}
returncountMap
}
Target platform: JVMRunning on kotlin v. 1.3.41
我们可以使用a算法。迭代所有值时,我们会查看地图以查看之前是否已经看到过。如果是这样,我们增加柜台;否则,我们将初始计数放入地图中。下一部分将显示一个类似但改进的解决方案。
具有显式默认值的迭代解决方案
countMap。putIfAbsent(e,)
// getValue ,作为索引运算符的替代,确保返回不可为空的类型
countMap[e]=countMap。getValue(e)+1
目标平台:JVM上科特林V上运行。1.3.41
作为前一解决方案的替代方案,我们可以利用确保元素初始化为0,以便我们可以安全地增加以下行中的计数器。在这种情况下我们做的是提供显式默认值。另一个类似的工具是:
countMap[e]=countMap。getOrDefault(e,)+1
目标平台:JVM上科特林V上运行。1.3.41
提供明确的默认值或通过简单易懂的解决方案,但我们可以做得更好。
具有隐式默认值的迭代解决方案
类似Python的,科特林提供了一个整洁的扩展名为,它看起来是这样的:
这个扩展让我们为地图中没有关联值的键提供初始化程序。让我们在我们的解决方案中使用它:
funcountOccurrences(values:Collection):Map{
valcountMap=mutableMapOf()。withDefault{}
for(einvalues){
countMap[e]=countMap。getValue(e)+1
}
返回countMap
}
目标平台:JVM上科特林V上运行。1.3.41
它进一步简化了代码,因为我们不再需要在迭代中处理未知值。由于我们使用的是默认地图,因此我们可以安全地从中获取值并随时增加计数器。
重要的提示
使用扩展时需要注意一件重要的事情,这是其文档的一部分:
[...]当原始地图不包含指定键的值时使用此隐式默认值,并使用[Map.getValue]函数[...]获取值
只有在使用时才会提供默认值,这在使用索引运算符访问地图时不是这种情况,如此处所示(点击运行按钮):
funmain(){
valmap=mutableMapOf()。withDefault{}
println(map[“hello”])
的println(地图。的getValue(“你好”))
}
目标平台:JVM上科特林V上运行。1.3.41
原因是界面的合同,其中说:
返回与给定[key]对应的值,或者如果地图中不存在这样的键。
由于默认地图想要履行这个合同,他们不能返回任何东西,但是在不存在密钥的情况下,这已经在Kotlin论坛中讨论过了。
让我们去惯用吧
好吧,所以看到Kotlin确实带有地图中的默认值,这太棒了。但是,编写代码是不是像上面的例子中那样惯用?我认为这取决于。使用Kotlin出色的功能API可以更简单地解决大多数情况,这些API带有内置的分组和计数功能。然而,了解替代方案是很好的,因为在某些情况下,您可能会选择采用迭代方法。让我为您提供代码的简化版本:
funcountOccurrences(values:Collection):Map=
mutableMapOf().withDefault{}.apply{
for(einvalues) {
put(e,getValue(e)+1)
}
}
它仍然使用显式循环,但通过使用它简化了允许我们在单个语句中初始化映射。
在Kotlin中有很多方法可以解决给定的问题,但最简单的方法可能是一种功能性方法:
funcountOccurrences(values:Collection):Map=
价值观。groupingBy{it}。eachCount()
目标平台:JVM上科特林V上运行。1.3.41
结论
如本小文所示,您可以使用Kotlin以多种不同方式解决简单算法。与Python类似,您可以使用默认值提供程序初始化映射,但需要注意常规索引操作访问将无法按预期方式工作。如文档所述,必须使用该功能。由于Kotlin附带了一个非常有用的标准库,因此您需要考虑尽可能多地使用它。这意味着在大多数情况下,实现分组或计数等常见事项不应从头开始实现,而应使用标准库中的现有功能来实现。
领取专属 10元无门槛券
私享最新 技术干货