我发现了这个:
fun main() {
val list: MutableList<Int> = mutableListOf(1, 2, 3, 4, 5)
list.removeAll { x -> x in 1..3 } // [4, 5]
list.removeIf { x -> x in 1..3 } // [4, 5]
}
两者都产生相同的结果。
虽然我知道removeAll
是Kotlin,removeIf
是Java,但我不明白为什么removeIf
已经在那里了,removeAll
还在那里?
事实上,我们可以在Kotlin中使用removeIf
而不会有任何麻烦,或者是否有任何用例可能需要一个又一个?
4条答案
按热度按时间6gpjuf901#
还有一个重要的区别:
在
CopyOnWriteArrayList
上调用removeIf
是线程安全的,但是removeAll
是不是。看一下代码,
removeIf
有一个CopyOnWriteArrayList
的自定义实现,但是removeAll
迭代索引,最终将抛出ArrayIndexOutOfBoundsException
,甚至更糟,如果并发调用,将删 debugging 误的元素。sg2wtvxw2#
Java的
removeIf()
从Java 1.8开始就存在了。Kotlin从2011年开始(wikipedia),Java 1.8出现在2014年。
我不确定Kotlin的
removeAll(predicate)
是什么时候被指定和实现的,但是它可能早于Java的removeIf()
。7gcisfzg3#
这是两个非常不同的函数,但是在Kotlin中这个方法被重载了,这意味着,它有两种不同类型的参数。
如果你读了文档,你会发现你可以通过给一个集合来使用这个函数:
或者给一个函数来过滤:
所以,第二个类似于Java版本的removeIf,第一个不是。
nxagd54h4#
两者都产生相同的结果。
结果是以完全不同的方式实现的,所以它可能不总是完全相同的。
removeAll
是一个方便的方法,它是一个多次调用removeAt
的简单循环。removeIf
是一个原生的ArrayList
方法,它直接操作内部elementData
,绕过所有旧的删除方法和任何可能放在那里的逻辑。这里的坏消息是,它被追溯性地覆盖应用到从ArrayList
派生的所有内容,而忽略旧的实现。或者,是否有任何用例可能需要一个而不是另一个?
一个例子是
androidx.databinding.ObservableList
,它早于removeIf
,并且不发送到期删除通知,因此要么默默地破坏代码,要么导致cryptic errors。