【问题标题】:Does Kotlin's version of Java's for each have the same limitations?每个 Kotlin 版本的 Java 是否有相同的限制?
【发布时间】:2020-10-10 19:12:55
【问题描述】:

我目前正在学习来自 Java 的 Kotlin。在Java中,做

for(String s:stringList){
   if(condition == true) stringList.remove(s);
}

不起作用,因为您只能使用 for each 读取数据。这也适用于 Kotlin 吗?

【问题讨论】:

    标签: java kotlin foreach


    【解决方案1】:

    这与 Java 中的限制相同 - 当您迭代集合时,您只能通过 Iteratorremove() 方法对其进行修改

    从底层集合中移除此迭代器返回的最后一个元素(可选操作)。每次调用 next() 时只能调用一次此方法。 如果在迭代过程中通过调用此方法以外的任何方式修改了底层集合,则迭代器的行为是不确定的

    Kotlin 有 its own equivalent(请记住 Kotlin 使用可变和不可变列表的概念,因此您只能使用 MutableList 来做到这一点)

    foreach / 增强的for 结构的问题在于它没有公开您需要调用remove()Iterator,并且不允许您在集合本身上调用remove() .和 Kotlin 一样 - 所以你的选择基本上是

    • 使用for/forEach(但不能修改集合)
    • 调用集合的iterator() 方法并自己对其进行迭代(现在您可以在其上调用remove(),但有我引用的限制)
    • 避免可变性并生成新集合

    最后一个是在 Kotlin 中鼓励你做的事情——不要修改集合,而是尝试使用不可变的集合并将它们转换为新的集合:

    stringList.filterNot { condition }

    如果您熟悉所有 collection functions(是的,有很多 个),您就会了解将 A 转换为 B 的方法以及便利功能可以帮助您做到这一点(例如filterTo,它允许您提供MutableList 来填充您想要保留的项目)。

    如果您确实想就地修改可变集合,这是可能的,但您必须自己管理它,因为它本质上是危险的,并且系统无法保证您安全地进行操作。

    【讨论】:

    • 有一种更实用的方式来就地改变列表:removeAll(predicate: (T) -> Boolean)。但是,是的,大多数情况下,最好使用filter() 或类似名称来创建新列表。
    • 哦,是的,这实际上非常适合 OP 尝试做的事情!虽然我假设它会在后台创建另一个 Collection,因此它可以执行通常的 removeAll(elements) 调用 - 所以如果就地改变列表是关于内存效率或其他问题,那么请记住这一点。
    • 实际上,看起来removeAll()的谓词版本的当前实现非常高效:对于RandomAccess列表,例如ArrayList,它对列表进行单次扫描,复制项目就地。 (如果不是RandomAccess,它会回退到在迭代器上调用remove()。) 当然,这只是一个实现细节,不能保证;但未来的版本不太可能降低性能。
    • 哦,太好了,感谢您的检查!不要像我一样懒惰......但它确实表明,尽可能利用库函数是一个好主意 - 有很多人正在努力制作这些简洁高效的实现,所以你不要'不必担心自己做。因此,如果有一个功能可以满足您的需求,您应该使用它!
    【解决方案2】:

    是的,如果你用 Kotlin 重写这段代码,你会遇到同样的并发修改问题:

    for (s in stringList) {
       if(condition == true) stringList.remove(s)
    }
    

    为避免此问题,您可以从可变列表中获取可变迭代器,并使用它随时删除元素。但与 Java 不同的是,您不必使用 hasNext()/next() 调用手动迭代它——您可以使用相同的 for 运算符来迭代它:

    val iterator = stringList.iterator()
    for (s in iterator) {
       if (condition == true) iterator.remove()
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-14
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-03
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      相关资源
      最近更新 更多