Have you ever used a default map or default dict before? If you know Python a bit, you probably saw its defaultdict in action at some point. Kotlin also comes with a similar tool which I want to demonstrate in this little article.
You can find the Python defaultdict documentation and some examples 这里 但基本用例显示在以下代码段中:

from collections import defaultdict 

d = defaultdict(int)
print(d["someKey"]) //0

The defaultdict can also be used with other types and makes sure that you don't get a KeyError when running your code. Instead, it provides a default value for unknown keys, which can be really helpful for grouping and counting algorithms like the following one:

from collections import defaultdict 

data = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in data:

print(d.items()) # dict_items([('red', {1, 3}), ('blue', {2, 4})])




fun <T> countOccurrences(values: Collection<T>): Map<T, Int>



fun <T> countOccurrences(values: Collection<T>): Map<T, Int> {
    val countMap = mutableMapOf<T, Int>()
    for (e in values) {
        val current = countMap[e]
        if (current == null) countMap[e] = 1 
        else countMap[e] = current + 1
    return countMap

We can use a MutableMap for this algorithm. When iterating all values, we look into the map to see whether it has been seen before. If so, we increment the counter; otherwise, we put an initial count of 1 into the map. A similar, but improved, solution is shown in the next part.


countMap.putIfAbsent(e, 0)
// getValue, as an alternative to index operator, assures that a non-nullable type is returned
countMap[e] = countMap.getValue(e) + 1 

As an alternative to the previous solution, we can make use of putIfAbsent to ensure that the element is initialized with 0 so that we can safely increment the counter in the following line. What we do in this case is providing an explicit default value. Another similar tool is getOrDefault:

countMap[e] = countMap.getOrDefault(e, 0) + 1

Providing explicit defaults via putIfAbsent or getOrDefault leads to easy and understandable solutions, but we can do better.


Similar to Python's defaultdict, Kotlin comes with a neat 扩大 called MutableMap::withDefault and it looks like this:

fun <K, V> MutableMap<K, V>.withDefault(defaultValue: (key: K) -> V): MutableMap<K, V>


fun <T> countOccurrences(values: Collection<T>): Map<T, Int> {
    val countMap = mutableMapOf<T, Int>().withDefault { 0 }
    for (e in values) {
        countMap[e] = countMap.getValue(e) + 1
    return countMap



There's one important thing you need to be aware of when using the withDefault extension, which is part of its documentation:

[...]当原始贴图不包含指定密钥的值时使用此隐式默认值,并且值是 用[map.getValue]功能获得 [...]

The default value will only be provided if you use Map::getValue, which is not the case when accessing the map with index operators as you can observe here (hit the run button):

fun main(){
    val map = mutableMapOf<String, Int>().withDefault { 0 }

The reason for this is the contract of the Map interface, which says:

Returns the value corresponding to the given [key], or null if such a key is not present in the map.

Since default maps want to fulfill this contract, they cannot return anything but null in the case of non-existent keys, which has been discussed in the kotlin论坛 before.



fun <T> countOccurrences(values: Collection<T>): Map<T, Int> =
    mutableMapOf<T, Int>().withDefault { 0 }.apply {
        for (e in values) {
            put(e, getValue(e) + 1)

It still uses an explicit for loop but got simplified by the use of apply which allows us to initialize the map in a single statement.

有几十种方法可以在Kotlin中解决给定的问题,但可能是最简单的问题 功能方法:

fun <T> countOccurrences(values: Collection<T>): Map<T, Int> =
    values.groupingBy { it }.eachCount()


As shown in this little article, you can solve simple algorithms in many different ways using Kotlin. Similar to Python, you can initialize a map with a default value provider but need to be aware that the regular index operation access won't work the way you might expect. As documented, the getValue function has to be used. Since Kotlin comes with a very useful standard library, you want to consider using it as much as possible. This means that implementing common things like grouping or counting should, in most cases, not be implemented from scratch but rather be done with existing functionalities from the standard library.

One thought on “Kotlin的默认地图


您的电子邮件地址不会被公开。 必需的地方已做标记 *