HashMap忽略了覆盖的hashCode和equals方法

时间:2019-10-11 14:30:11

标签: java hash hashmap hashcode

我正在从文件加载有关网络流量的数据。我正在加载的信息是攻击者的IP地址,受害者的IP地址和日期。我将这些数据组合到一个Traffic对象中,为此我定义了hashCodeequals函数。尽管如此,我将它们装入的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的内部工作方式正在忽略我的自定义hashCodeequals方法,但是如果是这种情况,那为什么呢?如果这个猜测是错误的,那么这里发生了什么?

1 个答案:

答案 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;
}
相关问题