HashSet 问题 — equals 和 hashCode with contains 的工作方式与我预期的不同
-
04-07-2019 - |
题
我有以下代码:
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现在使用哈希集:1 1 0
然而,我预计最后一行也为真(1)。我是否缺少一些明显的东西?
(是的,我知道我的 equals 方法和 hashcode 方法没有考虑到一些问题......它们故意很简单,但请告诉我是否存在导致此问题的问题)
解决方案
您不应该实现Java样式的equals和hashCode方法,而是实现Python等效代码 __ eq __
和 __ hash __
。添加
def __hash__(self):
return self.hashCode()
def __eq__(self, o):
return self.equals(o)
帮助。 这些python方法 - 据我所知 - 通过Jython动态绑定到hashCode和equals()。这确保您可以将Python类放入Java的集合中。
现在代码打印出五个“1”。
其他提示
我在Java中编写了等效的代码,它确实为所有三个contains()调用生成了true。所以我认为这在Jython中一定是个怪人。也许底层的Java对象并不像你在Python中看到的那样。
我不了解 Python,但看起来底层 Java 对象的 equals() 和 hashcode() 确实没有遵守所需的约定。
- 两个对象如果 equals() 必须返回相同的 hashcode()。
看来这已经被侵犯了。HashSet 首先在查找中使用哈希码来获取匹配对象所在的列表,然后遍历该列表以查找相等的对象。如果您的哈希码不遵守合同并且它们返回不同的哈希码,那么即使它们是 equals() 具有可比性,它也不会在哈希集中找到它。
默认的 Java Object.hashcode() 不会为 2 个对象返回相同的哈希码。你必须覆盖它。
不隶属于 StackOverflow