【问题标题】:Kotlin foreach on a map vs iterating over the keys when used with coroutines与协程一起使用时,地图上的 Kotlin foreach 与迭代键
【发布时间】:2019-01-12 05:05:36
【问题描述】:

我对以下代码的情况感到困惑。 task.yield 是从 a 到 b 的 hashmap,store.put 是一个挂起函数,它接受 a 和 a b。遍历地图的第一种方法没有问题,第二种方法也是如此。第三种方式对我来说是最自然的迭代方式,也是我最初编写的方式,它导致 kotlin 抱怨挂起函数只能在协程体中调用。 我猜这与地图上的 forEaching 的工作方式有关(可能与列表相反?)但我真的不明白问题出在哪里。

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 是一个内联函数,而我尝试使用的 map 不是。我猜这就是问题所在。

【问题讨论】:

    标签: kotlin kotlinx.coroutines suspend


    【解决方案1】:

    确实,接受(K, V) -> UnitBiConsumer<? super K, ​? super V>)的Map#forEach 的重载不是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&lt;K, V&gt;,因此您可以在lambda 中简单地destructure

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

    【讨论】:

      猜你喜欢
      • 2020-10-02
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 2019-06-22
      • 2015-06-30
      • 2019-08-19
      相关资源
      最近更新 更多