当尝试获取其中存在的对象时,Hashmap 给出 Null
我遇到了这个奇怪的问题,我正在迭代响应列表。当我尝试从问题的每个响应中获取答案时,大多数人都正确地得到了答案,除了从哈希映射中获取答案给出 null 的情况。我已经在 Eclipse 中运行了调试模式,并将我尝试从 hashmap getAnswerMap() 获取其值的问题与该 hashmap 中的值进行了比较,两者似乎完全相同,但我仍然得到 null。
for (SurveyResponse response : responses) { MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); .... .... }
然后,我认为这是一个哈希码问题,所以我添加了另一行丑陋的代码来检查哈希码,它们实际上具有相同的哈希码,并且附加的以下行有效并且确实正确设置了答案。
for (SurveyResponse response : responses) { MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); for (Entry entry: response.getAnswerMap().entrySet()) { if (entry.getKey().hashCode() == question.hashCode()) answer = (MultipleChoiceAnswer) entry.getValue(); .... .... }
然而,这非常丑陋,我真的很想从哈希图中得到正确的答案。有什么建议吗?
更新: 对两个对象同时调用 hashCode() 和 equals() 方法表明两者具有相同的哈希码,并且 equals() 返回 true。我怀疑,正如下面的答案之一所表明的那样,问题可能是在将问题插入哈希映射时使用不同的哈希码插入的。因此,调用相关 get 方法会返回 null,因为我尝试获取的对象没有与旧对象相同的哈希码。非常有帮助的答案伙计们!
I am running into this weird issue where I am iterating over a list of responses. when I try to get the answer from each response by the question, most of them get the answer correctly except one where getting the answer from the hashmap gives null. I have ran the debug mode in eclipse, and compared the question that I try to get its value from the hashmap getAnswerMap() with the one inside that hashmap and both seem to be exactly the same, but I still get null.
for (SurveyResponse response : responses) { MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); .... .... }
Then, I thought it is a hashcode issue, so I added another ugly line of code to check hashcodes, and they actually have the same hashcode and the additional following line worked and did set answer correctly.
for (SurveyResponse response : responses) { MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question); for (Entry entry: response.getAnswerMap().entrySet()) { if (entry.getKey().hashCode() == question.hashCode()) answer = (MultipleChoiceAnswer) entry.getValue(); .... .... }
However, this is very ugly and I would really like to get the answer correctly from the hashmap. Any suggestions?
UPDATE:
calling both hashCode() and equals() method on both objects shows that both have equal hashcodes and equals() returns true. I suspect that as one of the answers down indicate, the problem might be that the question was inserted with a different hashcode when it was inserted in the hashmap. Therefore, calling the get method in question returns null because the object I am trying to get does not have the same hashcode as the old one. Extremely helpful answers guys!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
需要注意的一件事:确保您用作键的类是不可变的 - 否则,当您将键放入时,它会散列为一件事,但当您取时会散列为不同的东西它出来了。
编辑:它不一定是不可变的,但它必须是真实的,它只能以不改变哈希码的方式进行更改。使整个对象不可变是最简单的方法,但这不是唯一的方法。
One thing to watch out for: Make sure the class you're using as a key is immutable -- otherwise, a key will hash to one thing when you put it in, but something different when you take it out.
Edit: It doesn't have to be immutable, but it has to be true that it can only be changed in a way that doesn't change the hashcode. Making the entire object immutable is the simplest way to do that, but it's not the only way.
另一种玻璃球猜测:
您有一个像这样的 equals 方法:
但是在这里您并没有真正从 Object 重写
equals(Object)
方法,而只是声明一个除此之外还有新的。 HashMap 对您的新方法一无所知,它只会调用原始方法来将映射中的键对象与查询键进行比较(在找到具有匹配 hashCode 的键之后)。相反,请像这样声明该方法:(
@Override
注释可让编译器检查您是否确实在此处重写了方法,而不仅仅是创建了一个新方法。)One more glass ball guess:
You have an equals method like this one:
But here you don't really override the
equals(Object)
method from Object, but simply declare a new one beside this. The HashMap does not know anything about your new method, it will simply call the original one for comparing your key object in the map with the query key (after finding one with matching hashCode).Declare the method like this, instead:
(The
@Override
annotation lets the compiler check that you are really overriding a method here, not just creating a new one.)要使用
HashMap
使对象成为 100% 确定性的键,您需要重写hashCode()
和equals()
,使它们在以下方面保持一致:当hashCode()
相同时,equals()
始终返回true
。这是 Brian Goetz 在 IBM DeveloperWorks 上发表的一篇旧文章 ,但内容今天仍然适用:
To make an object an 100% deterministic key with a
HashMap
you need to overridehashCode()
andequals()
where they are consistent in thatequals()
always returnstrue
when thehashCode()
s are the same.Here is an old article from Brian Goetz on IBM developerWorks, but the contents are still applicable today:
您可能没有正确重写
equals(..)
- 这是HashMap
正常工作的要求It's likely that you haven't overridden
equals(..)
correctly - it is a requirement for aHashMap
to work correctly