Kotlin在地图上进行foreach与与协程一起使用时遍历键

时间:2019-01-12 05:05:37

标签: kotlin kotlinx.coroutines suspend

我对以下代码发生了什么感到困惑。 task.yield是从a到b的哈​​希表,而store.put是一个使用a和b的暂停函数。遍历地图的第一种方法没有问题,第二种方法也没有问题。第三种方式对我来说是最自然的迭代方式,也是我最初编写的方式,它使Kotlin抱怨只能在协程体内调用暂停功能。 我猜想这与地图上的forEach的工作方式有关(也许与列表相对吗?),但我并不真正了解问题所在。

launch{
    // Kotlin is perfectly happy with this
    for(elt in task.yield.keys){
        store.put(elt,task.yield[elt]!!)
    }
    // and this
    task.yield.keys.forEach { 
        store.put(it,task.yield[it]!!)
    }
    // This makes kotlin sad. I'm not sure why
    task.yield.forEach { t, u ->
        store.put(t, u)
    }
}

编辑:我刚刚注意到forEach的列表是一个内联函数,而我尝试使用的地图则不是。我猜这是问题所在。

1 个答案:

答案 0 :(得分:3)

实际上,接受Map#forEach(K, V) -> Unit)的BiConsumer<? super K, ​? super V>的重载不是Kotlin标准库的一部分,而是JDK本身(Map#forEach)的一部分。 。这就解释了为什么在此块中执行的任何内容都不会内联,因此不属于封闭的“悬浮上下文”。

Kotlin提供了一个非常相似的功能,您可以使用:

inline fun <K, V> Map<out K, V>.forEach(action: (Entry<K, V>) -> Unit)
     

对每个条目执行给定的操作。
   kotlin-stdlib / kotlin.collections / forEach

这接受Entry<K, V>,因此您可以在lambda中简单地destructure

task.yield.forEach { (t, u) /* <-- this */ ->
    store.put(t, u)
}