【问题标题】:HashMaps getting different Hash Codes for same string and provinceHashMaps 为相同的字符串和省份获取不同的哈希码
【发布时间】:2020-05-22 09:04:20
【问题描述】:

我正在为不同的 int 值解析 3 个不同的 Json 数组。以下是 3 个数组的链接(由于某种原因,格式不允许我超链接)。
https://api.covid19api.com/country/canada/status/deaths/live?from=2020-05-01T00:00:00Z&to=2020-05-02T00:00:00Z
https://api.covid19api.com/country/canada/status/recovered/live?from=2020-05-01T00:00:00Z&to=2020-05-02T00:00:00Z
https://api.covid19api.com/country/canada/status/confirmed/live?from=2020-05-01T00:00:00Z&to=2020-05-02T00:00:00Z

我需要将其写入已正确实现的数据库中,但我的 Map 实现是错误的。截至目前,我知道这些数组的大小相同,因为它们涵盖了相同的日期范围。我正在遍历每个数组并创建 3 个单独的哈希映射。哈希映射的关键是我创建的自定义结构,它是一对字符串,值是我感兴趣的整数。我这样做是因为我知道,或者我相信在检查数组时,所有 3 个地图将包含相同的键集,因此相同的哈希码,所以当我在一个数组上调用 .get(key) 时,我也将能够获取与相同键(日期和省份)关联的值从其他地图。使用键值访问其他哈希映射会返回 null,但是,我对 equals 和 Hashcode 的单元测试是成功的。关于造成这种情况的一些帮助会很可爱。 (我知道我的自定义类名的拼写有误,但它与 ought 一致,我还没有重构)。我假设我的自定义结构中的哈希码有问题

 for (int i = 0; i <= arrayRecovered.length()-1; i++) {  // To loop over all json objects in the array and grab the required values needed. This is the loop for the recovered keyword

        String provinceRecovered = arrayRecovered.getJSONObject(i).getString("Province");
        String dateRecovered = arrayRecovered.getJSONObject(i).getString("Date");// 
        // of case should be on

        myStrucutre recoveredKey = new myStrucutre(dateRecovered, provinceRecovered);
        recoveredMap.put(recoveredKey, arrayRecovered.getJSONObject(i).getInt("Cases")); // Putting the value associated with the number of recovered cases in the province on the returned date.

        String provinceConfirmed = arrayConfirmed.getJSONObject(i).getString("Province"); //Getting province associated confirmed case at place i
        String dateConfirmed = arrayConfirmed.getJSONObject(i).getString("Date");
        myStrucutre confirmedKey = new myStrucutre(dateConfirmed, provinceConfirmed);
        confirmedMap.put(confirmedKey, arrayConfirmed.getJSONObject(i).getInt("Cases"));


        String provinceDeath = arrayDeaths.getJSONObject(i).getString("Province");
        String dateDeath = arrayDeaths.getJSONObject(i).getString("Date");


        myStrucutre deathKey = new myStrucutre(dateDeath, provinceDeath);
        deathsMap.put(deathKey, arrayDeaths.getJSONObject(i).getInt("Cases"));
    }

// 这是我自己的数据结构,用于实现 HASH MAP 和 HASH TABLES 的键值。当代表日期和省份的字符串相同时,我希望键相等。 // 所以我必须重写 hashcode 和 equals 来确保这一点。

private final String date;
private final String province;

public myStrucutre(String date, String province) {
    this.date = date;
    this.province = province;

}

public String getDate() {
    return date;
}

public String getProvince() {
    return province;
}

@Override // Want to make sure the Strings are equal then the keys are equal
public int hashCode() {
    int hash = super.hashCode();
    hash = 89 * hash + (date != null ? date.hashCode() : 0);
    hash = 89 * hash + (province != null ? province.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    myStrucutre thing = (myStrucutre) o;

    if (province != null ? !province.equals(thing.province) : thing.province != null) return false;

    return date != null ? date.equals(thing.date) : thing.date == null;
}

}

【问题讨论】:

  • 你为什么要考虑 super.hascode()?这将使相等对象的不同hascode。

标签: java arrays hashmap


【解决方案1】:

你说 “我知道,或者我相信在检查数组时,所有 3 个 Map 将包含相同的键集,因此具有相同的 Hashcode”

您想要的是 hashcode 应该完全依赖于关键字段 - 但这不是您实现它的方式,因为这一行:

int hash = super.hashCode();

您以超级的哈希码开始您的哈希码(对于不同的对象是不同的值),这意味着最终结果也包括该值 - 因此对于不同的对象将是不同的。

只需从 :

开始
int hash = 0;

那么哈希应该按照你的意愿行事。

【讨论】:

  • 非常感谢。我的愚蠢错误
【解决方案2】:

因为这个int hash = super.hashCode();,两个不同的对象有两个不同的super.hashCode();

这就是为什么你会得到两个不同的哈希码。

但如果你不扩展任何类,你不必调用super.hashCode(); int hash = 31 就够了。

【讨论】:

  • 啊,我明白了。非常感谢。我的愚蠢错误,自从我覆盖哈希码以来已经有一段时间了。
猜你喜欢
  • 2021-05-09
  • 2021-09-21
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 2011-11-12
相关资源
最近更新 更多