科特林';s版本的Java';对于每种类型,有相同的限制吗?

科特林';s版本的Java';对于每种类型,有相同的限制吗?,java,kotlin,foreach,Java,Kotlin,Foreach,我目前正在学习来自Java的Kotlin。在Java中,执行 for(String s:stringList){ if(condition == true) stringList.remove(s); } 不起作用,因为您只能使用for-each读取数据。这是否也适用于Kotlin?这与Java中的限制相同-当您对集合进行迭代时,只能通过迭代器的方法对其进行修改 从基础集合中移除此迭代器返回的最后一个元素(可选操作)。每次调用next()时只能调用此方法一次如果在迭代过程中以除调用此方法

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

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

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

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

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

Kotlin有(请记住Kotlin使用可变和不可变列表的概念,因此您只能通过
可变列表
来实现这一点)

foreach
/enhanced
for
结构的问题在于它没有公开需要调用的
remove()
迭代器,并且不允许对集合本身调用
remove()
。科特林也一样,所以你的选择基本上是

  • 使用
    for
    /
    forEach
    (但不能修改集合)
  • 调用集合的
    iterator()
    方法并自己对其进行迭代(现在您可以对其调用
    remove()
    ,我引用了一些限制)
  • 避免易变性并生成新集合
最后一个是鼓励您在Kotlin中执行的操作-与其修改集合,不如尝试使用不可变集合,并将其转换为新集合:

stringList.filterNot{condition}

如果你熟悉了所有这些(是的,有很多),你就会知道如何将a转换为B,以及有哪些方便的功能可以帮助你实现这一点(例如,它可以让你提供一个
MutableList
来填充你想要保留的项)


但是,如果您确实希望就地修改可变集合,这是可能的,但您必须自己管理它,因为这本身就很危险,而且系统无法保证您安全地执行此操作。

是的,如果您在Kotlin中重写此代码,您将遇到相同的并发修改问题:

用于(字符串列表中的){
如果(条件==true)stringList.remove
}
为了避免这个问题,您可以从可变列表中获取可变迭代器,并使用它在移动中删除元素。但与Java不同,您不必使用
hasNext()
/
next()
调用手动对其进行迭代-您可以使用相同的
for
运算符对其进行迭代:

val iterator=stringList.iterator()
for(迭代器中的s){
if(condition==true)迭代器.remove()
}

有一种更实用的方法可以改变列表:。 但是,大多数情况下,最好使用
filter()
或类似工具来创建一个新列表。哦,是的,这个列表实际上非常适合OP的尝试!虽然我假设它会在后台创建另一个集合,这样它就可以执行通常的
removeAll(elements)
调用-因此,如果在适当的位置对列表进行变异是为了提高内存效率或其他什么,这是需要记住的。实际上,它看起来像
removeAll()的谓词版本的当前实现
非常有效:对于
RandomAccess
列表,如
ArrayList
,它只需对列表进行一次扫描,即可将项目复制到位。 (如果不是
RandomAccess
,它会转而在迭代器上调用
remove()
。) 当然,这只是一个实现细节,不能保证;但是未来的版本不太可能降低性能。哦,太好了,谢谢你的检查!而不是像我一样懒惰。。。但这确实表明,尽可能地利用库函数是一个好主意——有很多人在努力实现这些简洁高效的实现,所以你不必担心自己去做。因此,如果有一个函数可以满足您的需要,您可能应该使用它!