尽管实现了 equals 和 hashcode 方法,Hashmap get 和 containskey 方法仍无法检索对象
Hashmap get and containskey method unable to retrieve object despite having implemented equals and hashcode methods
我有一个名为 Language
的 class,Language 有很多字段,但我只想使用一个字段来将它与其他 Language 对象进行比较。该字段称为 languageCode
,它是一个字符串。我已经使用Intellij Idea的方法生成工具自动实现了equals和hashcode。这是具有相关字段和生成方法的 class。
public class Language implements Serializable{
private String languageCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Language language = (Language) o;
return languageCode.equals(language.getLanguageCode());
}
@Override
public int hashCode() {
return Objects.hash(languageCode);
}
}
还有一个 class 叫做 Journal
期刊也有很多不同的领域,但只有一个是相关的,即:
public class Journal {
private Map<Language, String> titleTranslations = new HashMap<>()
}
在整个程序中,我使用常量变量 ENGLISH_LANGUAGE
,它包含来自数据库的英语表示语言对象。 titleTranslations
中的所有语言对象也来自同一个数据库 table。此外,Journal 在其 Hashmap titleTranslations 中肯定有一个英语语言对象。
但是当我运行进行以下测试时:
journal.getTitleTranslations().forEach((Language language, String string) ->{
log.info(language.getLanguageCode() + " " + string);
log.info("hashcode is " + language.hashCode());
});
log.info("default language " + ENGLISH_LANGUAGE.getLanguageCode());
log.info("hashcode is " + ENGLISH_LANGUAGE.hashCode());
log.info("contains key " + journal.getTitleTranslations().containsKey(ENGLISH_LANGUAGE));
log.info("key is not null " + (journal.getTitleTranslations().get(ENGLISH_LANGUAGE) != null));
它给出以下输出:
de deutsch
hashcode is 3232
en english
hashcode is 3272
fr francais
hashcode is 3307
nl nederlands
hashcode is 3549
defautl language en
hashcode is 3272
contiains key false
key is not null false
你可以看到,尽管 ENGLISH_LANGUAGE 的哈希码和 titletranslations 中的英语对象完全相同 (3272),但在使用 get 方法时仍然找不到密钥 returns false 当我使用 containsKey
并使用 ENGLISH_LANGUAGE 作为参数时。
有人可以告诉我我做错了什么吗?单字段哈希码实现是否以某种方式不起作用?
谢谢
好的,问题似乎与框架有关。因为我使用的框架使用像 hibernate 这样的代理子类,所以应该稍微调整 equals 方法。这是当您选中 Accept subclasses as parameter to equals() method
选项时 intellij 可以自动为您做的事情,复选框下方是这样的解释:
While generally incomplaint to Object.equals() specifiation accepting
subclasses might be necessary for generated method to work correctly
with frameworks, which generate Proxy subclasses like Hibernate
检查这个将创建一个 equals 方法,它使用这个 if 语句 if (!(o instanceof Language)) return false;
而不是这个 if (o == null || getClass() != o.getClass()) return false;
.
这以某种方式解决了问题。哈希码方法保持不变。完整代码如下:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Language)) return false;
Language language = (Language) o;
return getLanguageCode().equals(language.getLanguageCode());
}
@Override
public int hashCode() {
return Objects.hash(getLanguageCode());
}
我有一个名为 Language
的 class,Language 有很多字段,但我只想使用一个字段来将它与其他 Language 对象进行比较。该字段称为 languageCode
,它是一个字符串。我已经使用Intellij Idea的方法生成工具自动实现了equals和hashcode。这是具有相关字段和生成方法的 class。
public class Language implements Serializable{
private String languageCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Language language = (Language) o;
return languageCode.equals(language.getLanguageCode());
}
@Override
public int hashCode() {
return Objects.hash(languageCode);
}
}
还有一个 class 叫做 Journal
期刊也有很多不同的领域,但只有一个是相关的,即:
public class Journal {
private Map<Language, String> titleTranslations = new HashMap<>()
}
在整个程序中,我使用常量变量 ENGLISH_LANGUAGE
,它包含来自数据库的英语表示语言对象。 titleTranslations
中的所有语言对象也来自同一个数据库 table。此外,Journal 在其 Hashmap titleTranslations 中肯定有一个英语语言对象。
但是当我运行进行以下测试时:
journal.getTitleTranslations().forEach((Language language, String string) ->{
log.info(language.getLanguageCode() + " " + string);
log.info("hashcode is " + language.hashCode());
});
log.info("default language " + ENGLISH_LANGUAGE.getLanguageCode());
log.info("hashcode is " + ENGLISH_LANGUAGE.hashCode());
log.info("contains key " + journal.getTitleTranslations().containsKey(ENGLISH_LANGUAGE));
log.info("key is not null " + (journal.getTitleTranslations().get(ENGLISH_LANGUAGE) != null));
它给出以下输出:
de deutsch
hashcode is 3232
en english
hashcode is 3272
fr francais
hashcode is 3307
nl nederlands
hashcode is 3549
defautl language en
hashcode is 3272
contiains key false
key is not null false
你可以看到,尽管 ENGLISH_LANGUAGE 的哈希码和 titletranslations 中的英语对象完全相同 (3272),但在使用 get 方法时仍然找不到密钥 returns false 当我使用 containsKey
并使用 ENGLISH_LANGUAGE 作为参数时。
有人可以告诉我我做错了什么吗?单字段哈希码实现是否以某种方式不起作用?
谢谢
好的,问题似乎与框架有关。因为我使用的框架使用像 hibernate 这样的代理子类,所以应该稍微调整 equals 方法。这是当您选中 Accept subclasses as parameter to equals() method
选项时 intellij 可以自动为您做的事情,复选框下方是这样的解释:
While generally incomplaint to Object.equals() specifiation accepting subclasses might be necessary for generated method to work correctly with frameworks, which generate Proxy subclasses like Hibernate
检查这个将创建一个 equals 方法,它使用这个 if 语句 if (!(o instanceof Language)) return false;
而不是这个 if (o == null || getClass() != o.getClass()) return false;
.
这以某种方式解决了问题。哈希码方法保持不变。完整代码如下:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Language)) return false;
Language language = (Language) o;
return getLanguageCode().equals(language.getLanguageCode());
}
@Override
public int hashCode() {
return Objects.hash(getLanguageCode());
}