Scala可变集:奇怪的行为

时间:2014-08-28 04:25:03

标签: scala set

我无法解释Scala集的这种行为。

让我们从一些定义开始。

import scala.collection.mutable.Set
case class Item(name: String, content: Set[Int])
val items: Set[Item] = Set.empty

我会在我的设置中添加一个项目。

items += Item("name", Set(1, 2, 3))

我会清空我的内心。

items.filter(_.name == "name") foreach (_.content -= 1)
items
// res7: scala.collection.mutable.Set[Item] = Set(Item(name,Set(2, 3)))

到目前为止一切顺利。

items.filter(_.name == "name") foreach (_.content -= 2)
items.filter(_.name == "name") foreach (_.content -= 3)
items
// res12: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))

完美!现在,我真正想做的是删除内部空集的条目。

items.retain(_.content.nonEmpty)
items
// res12: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))

没有工作。也许我做了相反的测试。

items.retain(_.content.isEmpty)
items
// res14: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))

也没有工作。也许过滤器不起作用。

items.filter(_.content.nonEmpty)
// res15: scala.collection.mutable.Set[Item] = Set()

过滤器工作正常。也许我无法改变它,因为它是一个val。

items += Item("name", Set.empty)
items
// res17: scala.collection.mutable.Set[Item] = Set(Item(name,Set()), Item(name,Set()))

我可以改变它。并添加...更多相同?也许他们完全不同。

items += Item("name", Set.empty)
items
// res19: scala.collection.mutable.Set[Item] = Set(Item(name,Set()), Item(name,Set()))

他们并非完全不同。我可以删除其中任何一个吗?

items -= Item("name", Set.empty)
items
// res21: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))

我可以删除一个。我可以删除另一个,我从一开始就试图删除的那个吗?

items -= Item("name", Set.empty)
items
// res23: scala.collection.mutable.Set[Item] = Set(Item(name,Set()))

不。发生了什么?我很困惑。

编辑,解决方案:

使用此Stackoverflow帖子Scala: Ignore case class field for equals/hascode?,我通过更改声明案例类的方式解决了这个问题:

case class Item(name: String)(val content: Set[Int])

这样,内部集合被忽略为哈希码并等于评估,但仍然可以作为字段访问。

1 个答案:

答案 0 :(得分:6)

更改Item时,content的哈希码会发生变化。由于Set(...)创建的集合是一个哈希集,因此如果其元素的哈希值发生变化,它就无法正常工作。请注意,Set[Item]是否可变是无关紧要的;只有content是可变的。

如果将可变对象放入哈希集中或将它们用作哈希映射的键,则必须确保1)它们在那里或2)它们没有发生变异hashCode方法很稳定。