HashMap忽略重写的hashCode和equals方法

问题描述 投票:-2回答:2

我正在从文件加载有关网络流量的数据。我正在加载的信息是攻击者的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方法,但是如果是这种情况,那为什么呢?如果这个猜测是错误的,那么这里发生了什么?

java hash hashmap hashcode
2个回答
0
投票

这里的问题是您的equals方法,该方法不会覆盖Object#equals。为了证明这一点,以下将使用@Override注释not进行编译:

@Override
public boolean equals(Traffic t) {
    return this.hashCode() == t.hashCode();
}

HashMap的实现使用Object#equalsnot您的自定义实现。您的equals方法应接受Object作为参数:

@Override
public boolean equals(Object o) {
    return hashCode() == o.hashCode();
}

但是,这仍然是equals的较差实现,因为完全不同的对象可能会意外共享相同的hashCode

© www.soinside.com 2019 - 2024. All rights reserved.