3

我有以下代码:

class IncidentTag:
     def __init__(self,tag):
        self.tag = tag
     def equals(self,obj):
        return self.tag.equals(obj.tag)
     def hashCode(self):
        return self.tag.hashCode()

from java.lang import String
from java.util import HashMap
from java.util import HashSet

tag1 = IncidentTag(String("email"))
tag1copy = IncidentTag(String("email"))
tag2 = IncidentTag(String("notemail"))

print tag1.equals(tag1copy)
print tag2.equals(tag2)

print "Now with HashSet:"

hSet = HashSet()
hSet.add(tag1)
hSet.add(tag2)

print hSet.contains(tag1)
print hSet.contains(tag2)
print hSet.contains(tag1copy)

输出是:1 1 现在使用 HashSet:1 1 0

但是,我本来希望最后一行也是true(1)。有什么明显的东西我失踪了。

(是的,我知道我的equals方法和hashcode方法没有考虑到一些问题......它们故意简单,但如果有问题导致这个问题,请告诉我。)

4

3 回答 3

10

你不应该实现 Java 风格的 equals 和 hashCode 方法,而是 Python equivaltents__eq____hash__. 添加

def __hash__(self):
    return self.hashCode()
def __eq__(self, o):
    return self.equals(o)

有帮助。据我所知,这些 python 方法是由 Jython 动态绑定到 hashCode 和 equals() 的。这确保您可以将 Python 类放入 Java 的集合中。

现在代码打印出五个“1”。

于 2008-10-23T18:16:54.130 回答
1

我用 Java 编写了等效的代码,它确实对所有三个 contains() 调用都产生了 true。所以我认为这在 Jython 中一定是个怪事。也许底层的 Java 对象并不完全是你在 Python 中看到的那样。

于 2008-10-23T17:33:01.753 回答
0

我不了解 Python,但它确实看起来底层 Java 对象的 equals() 和 hashcode() 没有遵守所需的合同。

  • 两个对象 if equals() 必须返回相同的 hashcode()。

好像违反了。HashSets 首先将在查找中使用哈希码来获取匹配对象所在的列表,然后遍历列表以找到相等的对象。如果您的哈希码不遵守合同并且他们返回不同的哈希码,那么即使它们是 equals() 可比的,它也不会在哈希集中找到它。

默认的 Java Object.hashcode() 不会为 2 个对象返回相同的哈希码。你必须覆盖它。

于 2008-10-23T22:18:48.697 回答