public class DemoHashSet {
private String name;
private String dob;
private String gender;
public DemoHashSet(String name, String dob, String gender) {
super();
this.name = name;
this.dob = dob;
this.gender = gender;
}
public String getName() {
return name;
}
public String getDob() {
return dob;
}
public String getGender() {
return gender;
}
@Override
public String toString() {
return name+" "+dob+" "+gender;
}
@Override
public boolean equals(Object o) {
return this.name.equals(((DemoHashSet)o).getName());
}
@Override
public int hashCode() {
int code = this.name.hashCode() + this.dob.hashCode() + gender.hashCode();
System.out.println("Hash Code: "+code);
return code;
}
public static void main(String args[]) throws ParseException {
Map<DemoHashSet, String> hmap = new HashMap<DemoHashSet, String>();
DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
DemoHashSet obj2 = new DemoHashSet("key2", "122990", "male");
DemoHashSet obj3 = new DemoHashSet("key3", "123990", "male");
DemoHashSet obj4 = new DemoHashSet("key4", "124990", "male");
DemoHashSet obj5 = new DemoHashSet("key5", "125990", "male");
hmap.put(obj1, "value1");
hmap.put(obj2, "value2");
hmap.put(obj3, "value3");
hmap.put(obj4, "value4");
hmap.put(obj5, "value5");
System.out.println("Get values: ");
System.out.println(hmap.get(new DemoHashSet("key1", "121990", "male")));
System.out.println(hmap.get(new DemoHashSet("key2", "122990", "male")));
}
}
在这段代码中,我重写了hashcode()和equals()函数
当我运行此代码时,我得到以下输出:
Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values:
Hash Code: 1457153183
value1
Hash Code: 1457182975
value2
当我只覆盖hashCode()函数并注释equlas()方法时,我得到以下输出:
Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values:
Hash Code: 1457153183
null
Hash Code: 1457182975
null
需要对此行为进行解释,因为在两种情况下计算的哈希码都相同,但在第二种情况下它会给出 null 。
答案 0 :(得分:2)
需要解释此行为
这是我应该期待的确切预期行为。为什么呢?
有关hascode的一件事,那就是你不能100%保证唯一对象的唯一性。这意味着在某些情况下
不同的对象可以有类似的hascode。
HashMap实现牢记这一点。所以当你传递一个密钥时,他们总是比较hascode
,然后检查相等性(参考检查然后是equals()
方法)。如果没有找到,则返回null
。你可以查看源代码:
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
此代码块说:
hash
(hascode)必须相同和强>
equals()
方法相等在你的情况下,当你注释equals方法时,使用了equals()方法的默认实现形式的超类,它实际上只检查了引用相等性。所以
DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
以后
new DemoHashSet("key1", "121990", "male") //ins hmap.get()
未引用相同的对象,因此equals()
返回false而get()
返回null
,因为找不到该键的匹配项。
根据您的实现存在equals()
方法时,您告诉这些对象是相同的,因为它们具有相同的名称。
哈希码无法保证并且不是平等。
答案 1 :(得分:2)
需要将此行为解释为两者中计算的哈希码 场景是相同的,但在第二种情况下它给出了null。
这一切都与hashmap的get
方法在内部工作有关。当您为get
调用hashmap的specified key
方法时,会调用此key's hashcode
方法来计算bucket location
。一旦获得存储桶位置,它会调用指定键的equals
方法与该存储桶内的现有对象(实际上是类Entry对象)进行比较,如果任何对象根据equals
方法等于指定对象,则返回该对象。
案例1:我正在重写hashcode()和equals()方法
hmap.get(new DemoHashSet("key1", "121990", "male"))
hmap.get(new DemoHashSet("key2", "122990", "male"))
根据你的equals方法实现,如果两个DemoHashSet对象具有相同的名称,则它们是相等的。这就是为什么你在这种情况下得到结果。
案例2:我只覆盖hashCode()函数并注释equlas()方法
hmap.get(new DemoHashSet("key1", "121990", "male"))
hmap.get(new DemoHashSet("key2", "122990", "male"))
在这种情况下,没有自定义equals方法实现可用,因此它将采用默认实现,并且根据默认实现 - 当且仅当它们的引用相同时,两个对象是相同的。因此即使new DemoHashSet("key1", "121990", "male")
和new DemoHashSet("key1", "121990", "male")
具有相同的值,它们也不相同。所以hashmap没有在那个桶中获取那些对象。这就是你得到空的原因。
了解更多信息:http://javarevisited.blogspot.in/2011/02/how-hashmap-works-in-java.html
答案 2 :(得分:1)
您正在使用HashMap
。在内部,HashMap
有许多存储桶,每个存储桶都有一个存储项目列表。
每当您致电HashMap.get()
时,HashMap
都会调用DemoHashSet.hashCode()
并使用关键参数(可能使用模数(%
)运算符)来确定哪个存储桶为看看。
然后,它将使用DemoHashSet.equals()
方法搜索此列表,以查看它是否可以与key参数匹配。如果equals()
返回true
,则会返回该值,否则为null
。
来自Object.equals()的文档:
请注意,通常需要覆盖hashCode方法 每当重写此方法时,都要保持一般 hashCode方法的契约,它声明了相等的对象必须 有相同的哈希码。
答案 3 :(得分:0)
hadCode()函数用于通过将对象的键派生到特定的段/桶来将对象存储在特定的段/桶中。要了解此方法的用途,您需要了解HashTable或HashMap如何在内部工作。维基百科是了解它的最佳来源。
equals()函数用于检查集合对象中是否存在特定的Object。
如果两个对象相等,则hasCode将相同但converse不为true。两个不同的对象可以具有相同的hashCode