比较对象等价于Ruby的

问题描述:

我在这里做一个Ruby教程: http://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/105-equality_of_objects比较对象等价于Ruby的

它说当我重载==运营商,我也应该重载eql?方法和散列方法,因为他们是“快”。

但是,如果我用三种方法重载所有这三种方法,其中一个比另一个更快?

+0

相关:http://*.com/questions/10257096/why-is-faster-than-eql – 2013-04-24 22:36:23

+0

@SemyonPerepelitsa:原来并不真正相关,但我很高兴能够回答这个棘手的问题: - ) – 2013-04-25 00:16:28

+0

感谢您回答! – 2013-04-25 00:34:06

在大多数情况下,==eql?有同样的结果。在某些情况下,eql?==更严格:

42.0 == 42 # => true 
42.0.eql?(42) # => false 

因此,如果您定义==你可能要定义eql?也(反之亦然)。

选择Hash类将使用eql?来区分不同的密钥,而不是==。这可能是==,介意你,但eql?更干净。

为避免花费大量时间致电eql?,计算散列值时要求两个对象eql?必须具有相同的散列值。该散列值的存储,这使得未来的查找非常简单:如果哈希代码不匹配,则值不eql? ...

出于这个原因,你必须在一个合理的方式定义hash如果你定义eql?

请注意,计算散列值几乎总是比与==eql?进行比较要贵。但是,一旦散列被计算出来,检查散列匹配是非常快的。

因为散列通常涉及非常多的比较,所以对每个键执行一次相对昂贵的散列计算,然后对每次查找执行一次。想象一下有10个条目的散列。在第一次查询完成之前,构建它将涉及到10个对hash的调用。第一次查找将会相对较快:一次调用hash,随后对哈希代码进行非常有效的比较(实际上比这更快,因为它们是“索引的”)。如果有一场比赛,我们仍然需要打电话给eql?以确保这是一场真正的比赛。实际上,两个不是eql?的对象可能具有相同的散列。唯一的保证是两个对象eql?必须具有相同的散列,但是两个不同的对象也可以具有相同的散列。

如果您想要使用Array代替,则每次查找时可能需要10次调用eql?

对于什么是值得的,我不认为你链接到的Ruby引擎是如此清晰。它忽略了这样一个事实,即计算hash可能是昂贵的,所以只有当它有意义时,即,当每个元素将被多次比较是一个很好的假设时才会这样做。此外,它自定义的eql?示例使用==来比较实例变量,这是一个耻辱。理想情况下,它将使用eql?作为一致性,与数组为==(如果其元素为==)以及数组为eql?(如果其元素为eql?)相同。最后,它应该提到Struct,它为你定义了体面的==,hasheql?

+0

中更加明确地感谢这里的详细解释,这绝对有助于清除它 – Ricky 2013-04-24 23:32:24

例如, Array#hash说 -

具有相同内容的两个数组将具有相同的哈希码(并将使用eql?进行比较)。

Array#==说:

平等 - 两个数组相等,如果它们包含相同数量的元素,并且如果每一个元素等于(根据对象#==)在other_ary的对应元素。

Array#eql?

返回true自我与他人是同一个对象,或者是具有相同内容的两个阵列。

所以按照文件很清楚,eql?速度更快,因为它使用hash值,与eql?。而#==做两件事情 -

阵列的
  1. 长度和
  2. 每个元素相等测试。
+0

那么为什么不比较使用==而不是eql?是否因为eql使用比较快的哈希代码?它不会在内部使用==来比较两个哈希码的等价性吗? – Ricky 2013-04-24 21:21:43

+0

谢谢!这很有道理 – Ricky 2013-04-24 21:29:26

+2

这个答案是错误的:'eql?'不使用'hash'值,并且不会比'=='更快。 – 2013-04-24 21:47:10