如果在Kotlin中修改了元素,则无法删除可变集中的元素

时间:2018-04-04 08:25:17

标签: kotlin

使用removeAll()时出现问题,无法正确删除某些对象。

data class Dog(var name: String)

val dog1 = Dog(name = "dodo")
val dog2 = Dog(name = "mimi")

val set = mutableSetOf<Dog>()
set.add(dog1)
set.add(dog2)

dog1.name = "dodo2"

val before_size = set.size // 2

set.removeAll { true }

val after_size = set.size  // why it is 1!?, I expect it should be 0

removeAll没有像我预期的那样发挥作用。可变集中仍然有一个元素。有什么想法吗?

2 个答案:

答案 0 :(得分:7)

dog1.name = "dodo2" 的Javadoc:

  

注意:如果将可变对象用作set元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为。

写作

equals

你做到了这一点,你以一种影响set.removeAll { true } 比较的方式改变了对象。具体来说,通过使用构造

LinkedHashSet

您在set.remove(it)中运行了一个访问每个元素的代码路径,测试其上的谓词,然后尝试将其删除,就像调用it一样。这将导致LinkedHashSet重新计算其哈希码,现在与将其插入集合时的哈希码不同。然后,it会查找相应的哈希桶,但无法在那里找到{{1}}。

答案 1 :(得分:1)

您将对象添加到集合后进行更改。应该避免这样做

您可以改为使用clear

set.clear()

或者移动对象的变异:

val dog1 = Dog(name = "dodo")
val dog2 = Dog(name = "mimi")

dog1.name = "dodo2"
val set = mutableSetOf(dog1, dog2)