我正在从文件加载有关网络流量的数据。我正在加载的信息是攻击者的IP地址,受害者的IP地址和日期。我将这些数据组合到一个Traffic
对象中,为此我定义了hashCode
和equals
函数。尽管如此,我将它们装入的HashMap
会将相同的Traffic
对象当作不同的键。整个Traffic对象以及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);
}
}
我无法说出我的哈希方法的优势,但是前两张照片的输出是相同的,这意味着至少在这种情况下适用。
由于a和b的数据相同(因此equals
返回true),并且哈希值相同,因此HashMap
应该将它们识别为相同,并将值从1更新为2创建具有值2的第二个条目的过程。不幸的是,它无法将它们识别为相同,并且最终打印的输出如下:
{packagename.Traffic@1c051=1, packagename.Traffic@1c051=2}
我对此的最佳猜测是HashMap
的内部工作方式正在忽略我的自定义hashCode
和equals
方法,但是如果是这种情况,那为什么呢?如果这个猜测是错误的,那么这里发生了什么?
答案 0 :(得分:4)
这里的问题是您的equals
方法,该方法不会覆盖Object#equals
。为了证明这一点,以下将不使用@Override
注释进行编译:
@Override
public boolean equals(Traffic t) {
return this.attacker.equals(t.getAttacker()) &&
this.victim.equals(t.getVictim()) &&
this.date == t.getDate();
}
HashMap
的实现使用Object#equals
,并且不是您的自定义实现。您的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;
}