我有一个不可变的类Set,Set [MyClass],我想使用Set方法intersect和diff,但我希望它们使用我的自定义equals方法测试相等性,而不是默认对象相等性测试< / p>
我已经尝试重写==运算符,但它没有被使用。
提前致谢。
编辑:
intersect方法是GenSetLike
的具体值成员规范:http://www.scala-lang.org/api/current/scala/collection/GenSetLike.html src: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
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
我不清楚在没有谓词的情况下调用它时使用的是什么,p。这不是一个隐含的参数。
答案 0 :(得分:50)
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))
你无法覆盖AnyRef中的==(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)
答案 1 :(得分:8)
您还需要覆盖.hashCode
。当您覆盖.equals
时,情况几乎总是如此,因为.hashCode
通常被用作.equals
的更便宜的预检;任何两个相等的对象必须具有相同的哈希码。我猜你正在使用默认hashCode
不尊重这个属性的对象与你的自定义相等,并且Set实现基于哈希码做出假设(所以从来没有调用你的相等操作)
请参阅Any.equals
和Any.hashCode
的Scala文档:http://www.scala-lang.org/api/rc/scala/Any.html
答案 2 :(得分:1)
This answer shows a custom mutable Set with user-defined Equality。可以通过用Vector
替换内部存储并在每次操作时返回自身的修改副本来使其不可变
答案 3 :(得分:0)
&#34;无法直接覆盖==,因为它被定义为Any类中的最终方法。也就是说,Scala将==视为在Any类中定义如下:
final def == (that: Any): Boolean =
if (null eq this) {null eq that} else {this equals that}
&#34;来自Scala编程,第二版