问题描述
我有一个类的不可变 Set,Set[MyClass],我想使用 Set 方法 intersect 和 diff,但我希望他们使用我的自定义 equals 方法而不是默认对象相等性测试来测试相等性
I have an immutable Set of a class, Set[MyClass], and I want to use the Set methods intersect and diff, but I want them to test for equality using my custom equals method, rather than default object equality test
我已经尝试覆盖 == 运算符,但它没有被使用.
I have tried overriding the == operator, but it isn't being used.
提前致谢.
intersect方法是GenSetLike的具体值成员
The intersect method is a concrete value member of GenSetLike
规范:http://www.scala-lang.org/api/current/scala/collection/GenSetLike.htmlsrc: 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
所以交集是使用过滤方法完成的.
so the intersection is done using the filter method.
又一个
过滤器在 TraversableLike 中定义
filter is defined in 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.这不是隐式参数.
What's unclear to me is what it uses when invoked without a predicate, p. That's not an implicit parameter.
推荐答案
equals 和 hashCode 仅在您未定义它们的情况下才会在 case 类中自动提供.
equals and hashCode are provided automatically in case class only if you do not define them.
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调用版本
If what you want is reference equality, still write equals and hashCode, to prevent automatic generation, and call the version from 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)
,它是密封的并且总是调用 equals.如果您尝试定义一个新的(重载的)==(m:MyClass)
,它不是 Set
调用的那个,所以它在这里是没用的,而且通常非常危险.
You cannot override the ==(o: Any)
from AnyRef, which is sealed and always calls equals. If you tried defining a new (overloaded) ==(m: MyClass)
, it is not the one that Set
calls, so it is useless here and quite dangerous in general.
对于filter
的调用,之所以起作用,是因为Set[A]
是一个Function[A, Boolean]
.是的,使用了 equals
,你会看到函数实现 (apply
) 是 contains
的同义词,而大多数 的实现Set
在 contains 中使用 ==
(SortedSet
使用 Ordering
代替).==
调用 equals
.
As for the call to filter
, the reason it works is that Set[A]
is a Function[A, Boolean]
. And yes, equals
is used, you will see that function implementation (apply
) is a synonymous for contains
, and most implementations of Set
use ==
in contains (SortedSet
uses the Ordering
instead). And ==
calls equals
.
注意:我的第一个 equals
的实现又快又脏,如果要对 MyClass 进行子类化,可能会很糟糕.如果是这样,您至少应该检查类型相等性(this.getClass == that.getClass
)或更好地定义 canEqual
方法(您可以阅读 Daniel Sobral)
Note: the implementation of my first equals
is quick and dirty and probably bad if MyClass is to be subclassed . If so, you should at the very least check type equality (this.getClass == that.getClass
) or better define a canEqual
method (you may read this blog by Daniel Sobral)
这篇关于如何定义不可变的 Set 比较方法将使用的自定义相等操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!