我有一个不可变的类 Set[MyClass],我想使用 Set 方法 intersect 和 diff,但我希望它们使用我的自定义 equals 方法而不是默认对象相等性测试来测试相等性
我已经尝试覆盖 == 运算符,但它没有被使用。
提前致谢。
编辑:
intersect 方法是 GenSetLike 的具体值成员
规范:http://www.scala-lang.org/api/current/scala/collection/GenSetLike.html
来源:https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/GenSetLike.scala#L1
def intersect(that: GenSet[A]): Repr = this filter that
所以交集是使用过滤方法完成的。
另一个编辑:
过滤器在 TraversableLike 中定义
规范:http://www.scala-lang.org/api/current/scala/collection/TraversableLike.html
来源:https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/TraversableLike.scala#L1
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
我不清楚的是它在没有谓词的情况下调用时使用什么,p。这不是一个隐式参数。
最佳答案
仅当您未定义它们时,才会在 case 类中自动提供 equals 和 hashCode。
case class MyClass(val name: String) {
override def equals(o: Any) = o match {
case that: MyClass => that.name.equalsIgnoreCase(this.name)
case _ => false
}
override def hashCode = name.toUpperCase.hashCode
}
Set(MyClass("xx"), MyClass("XY"), MyClass("xX"))
res1: scala.collection.immutable.Set[MyClass] = Set(MyClass(xx), MyClass(XY))
如果你想要的是引用相等,还是写equals和hashCode,防止自动生成,从AnyRef调用版本
override def equals(o: Any) = super.equals(o)
override def hashCode = super.hashCode
接着就,随即:
Set(MyClass("x"), MyClass("x"))
res2: scala.collection.immutable.Set[MyClass] = Set(MyClass(x), MyClass(x))
您不能覆盖
==(o: Any)
来自 AnyRef,它是密封的并且总是调用 equals。如果您尝试定义一个新的(重载的)==(m: MyClass)
,不是Set
调用,所以它在这里没用,一般来说非常危险。至于调用
filter
,它起作用的原因是Set[A]
是 Function[A, Boolean]
.是的,equals
使用时,您会看到函数实现( apply
)是 contains
的同义词,以及 Set
的大多数实现使用 ==
在包含(SortedSet
使用 Ordering
代替)。和==
来电equals
.注:我第一次执行
equals
如果要对 MyClass 进行子类化,它又快又脏,而且可能很糟糕。如果是这样,您至少应该检查类型相等( this.getClass == that.getClass
)或更好地定义 canEqual
方法(您可以阅读 Daniel Sobral 的 this blog)
关于scala - 如何定义不可变的 Set 比较方法将使用的自定义相等操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7681183/