当我重写hashcode并从hashmap

时间:2015-08-05 04:43:56

标签: java hashmap equals hashcode

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

4 个答案:

答案 0 :(得分:2)

需要解释此行为
这是我应该期待的确切预期行为。为什么呢?
有关hascode的一件事,那就是你不能100%保证唯一对象的唯一性。这意味着在某些情况下 不同的对象可以有类似的hascode。

HashMap实现牢记这一点。所以当你传递一个密钥时,他们总是比较hascode,然后检查相等性(参考检查然后是equals()方法)。如果没有找到,则返回null。你可以查看源代码:

if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))

此代码块说:

    对于给定的密钥和条目密钥,
  • hash(hascode)必须相同

  • 给定密钥和输入密钥需要是相同的对象(相同的参考) OR 它们需要由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