[英]HashMap ignoring overridden hashCode and equals methods
I am loading data on network traffic from a file.我正在从文件中加载有关网络流量的数据。 The information I'm loading is attacker IP address, victim IP address, and date.
我正在加载的信息是攻击者 IP 地址、受害者 IP 地址和日期。 I've combined these data into a
Traffic
object, for which I've defined the hashCode
and equals
functions.我已将这些数据组合成一个
Traffic
object,为此我定义了hashCode
和equals
函数。 Despite this, the HashMap
I'm loading them into treats identical Traffic
objects as different keys.尽管如此,我正在将它们加载到的
HashMap
将相同的Traffic
对象视为不同的键。 The entire Traffic object complete with some simple test code in the main
method follows:整个Traffic object在
main
方法中加上一些简单的测试代码如下:
import java.util.HashMap;
public class Traffic {
public String attacker;
public String victim;
public int date;
//constructors, getters and setters
@Override
public int hashCode() {
long attackerHash = 1;
for (char c:attacker.toCharArray()) {
attackerHash = attackerHash * Character.getNumericValue(c) + 17;
}
long victimHash = 1;
for (char c:victim.toCharArray()) {
victimHash = victimHash * Character.getNumericValue(c) + 17;
}
int IPHash = (int)(attackerHash*victimHash % Integer.MAX_VALUE);
return (IPHash + 7)*(date + 37) + 17;
}
public boolean equals(Traffic t) {
return this.attacker.equals(t.getAttacker()) && this.victim.equals(t.getVictim()) && this.date == t.getDate();
}
public static void main(String[] args) {
Traffic a = new Traffic("209.167.099.071", "172.016.112.100", 7);
Traffic b = new Traffic("209.167.099.071", "172.016.112.100", 7);
System.out.println(a.hashCode());
System.out.println(b.hashCode());
HashMap<Traffic, Integer> h = new HashMap<Traffic, Integer>();
h.put(a, new Integer(1));
h.put(b, new Integer(2));
System.out.println(h);
}
}
I can't speak to the strength of my hash method, but the outputs of the first two prints are identical, meaning it at least holds for this case.我不能说我的 hash 方法的强度,但前两个打印的输出是相同的,这意味着它至少适用于这种情况。
Since a and b are identical in data (and therefore equals
returns true), and the hashes are identical, the HashMap
should recognize them as the same and update the value from 1 to 2 instead of creating a second entry with value 2. Unfortunately, it does not recognize them as the same and the output of the final print is the following:由于 a 和 b 的数据相同(因此
equals
返回 true),并且哈希值相同,因此HashMap
应该将它们识别为相同并将值从 1 更新为 2,而不是创建第二个值为 2 的条目。不幸的是,它不认为它们是相同的,最终打印的 output 如下:
{packagename.Traffic@1c051=1, packagename.Traffic@1c051=2}
My best guess at this is that HashMap
's internal workings are ignoring my custom hashCode
and equals
methods, but if that's the case then why?我对此的最佳猜测是
HashMap
的内部工作忽略了我的自定义hashCode
和equals
方法,但如果是这样,那为什么呢? And if that guess is wrong then what is happening here?如果这个猜测是错误的,那么这里发生了什么?
The problem here is your equals
method, which does not override Object#equals
.这里的问题是您的
equals
方法,它不会覆盖Object#equals
。 To prove this, the following will not compile with the @Override
annotation:为了证明这一点,以下代码不会使用
@Override
注释进行编译:
@Override
public boolean equals(Traffic t) {
return this.attacker.equals(t.getAttacker()) &&
this.victim.equals(t.getVictim()) &&
this.date == t.getDate();
}
The implementation of HashMap
uses Object#equals
and not your custom implementation. HashMap
的实现使用Object#equals
而不是您的自定义实现。 Your equals
method should accept an Object
as a parameter instead:您的
equals
方法应该接受Object
作为参数:
@Override
public boolean equals(Object o) {
if (!(o instanceof Traffic)) {
return false;
}
Traffic t = (Traffic) o;
return Objects.equals(attacker, t.attacker) &&
Objects.equals(victim, t.victim) &&
date == t.date;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.