基于传递的字符串长度的Hashcode方法实现

时间:2015-05-05 17:45:58

标签: java scjp

public class Dog {

    String name;

    public Dog(String name) {
        this.name = name;
    }

    public boolean equals(Object o) {
        if ((this == o) && ((Dog) o).name == name) {
            return true;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return name.length();
    }
}

class Cat {
}

enum Pets {

    DOG, CAT, HORSE
}

class MapTest {

    public static void main(String[] args) {
        Map<Object, Object> m = new HashMap<Object, Object>();
        m.put("k1", new Dog("aiko"));
        m.put("k2", Pets.DOG);
        m.put(Pets.CAT, "CAT Key");
        Dog d1 = new Dog("Clover");
        m.put(d1, "Dog key");
        m.put(new Cat(), "Cat key");
        System.out.println(m.get("k1"));
        String k2 = "k2";
        System.out.println(m.get(k2));
        System.out.println(m.get(Pets.CAT));
        System.out.println(m.get(d1));
        System.out.println(m.get(new Cat()));

        // UNABLE TO UNDERSTAND BELOW PART OF CODE
        d1.name = "magnolia";
        System.out.println(m.get(d1)); // #1 //prints Dog Key
        d1.name = "clover";
        System.out.println(m.get(new Dog("clover"))); // #2 // prints null
        d1.name = "arthur";
        System.out.println(m.get(new Dog("clover"))); // #3 // prints null 
    }
}

我正在尝试理解kathy的hashcode()实现和SCJP6的berts书。虽然我对哈希码实现有基本的了解,但本书中的一个场景让我感到困惑,而且我对输出感到困惑。

根据上述计划,它说:

  • 在第一次调用get()时,哈希码是8(木兰)和它 应该是6(三叶草),所以检索在步骤1失败,我们得到 空。
  • 在第二次调用get()时,哈希码都是6,所以步骤1 成功。一旦进入正确的桶(“名称长度= 6”) bucket),调用equals()方法,因为Dog的等于() 方法比较名称,equals()成功,输出为Dog key。
  • 在get()的第三次调用中,哈希码测试成功,但是 equals()测试失败,因为亚瑟不等于三叶草。

以上三行讨论了名称的长度及其相关的hashcode()实现,但是如何比较调用get()方法时的长度?

2 个答案:

答案 0 :(得分:2)

equals实现与文本说的不匹配。对于不同的物体永远不会是真的! hashcode也应该有一个大写C hashCode。此代码的工作原理如下:

import java.util.*;
class MapTest {

static class Dog {

    String name;

    public Dog(String name) {
        this.name = name;
    }

    public boolean equals(Object o) {
        if ((this == o)) {
            return true;
        } else if (((Dog)o).name.equals(this.name)) {
            return true;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return name.length();
    }
}

static class Cat {
}

static enum Pets {

    DOG, CAT, HORSE
}
    public static void main(String[] args) {
        Map<Object, Object> m = new HashMap<Object, Object>();
        m.put("k1", new Dog("aiko"));
        m.put("k2", Pets.DOG);
        m.put(Pets.CAT, "CAT Key");
        Dog d1 = new Dog("Clover");
        m.put(d1, "Dog key");
        m.put(new Cat(), "Cat key");
        System.out.println(m.get("k1"));
        String k2 = "k2";
        System.out.println(m.get(k2));
        System.out.println(m.get(Pets.CAT));
        System.out.println(m.get(d1));
        System.out.println(m.get(new Cat()));
        // UNABLE TO UNDERSTAND BELOW PART OF CODE
        d1.name = "magnolia";
        System.out.println(m.get(d1)); // #1 
        d1.name = "clover";
        System.out.println(m.get(new Dog("clover"))); // #2
        d1.name = "arthur";
        System.out.println(m.get(new Dog("clover"))); // #3
    }
}

编辑:并回答&#34;如何比较调用get()方法时的长度?&#34;:

put使用hashCode()来计算将放置值(和键)的存储区。

get()将首先查找存储桶。存储桶由hashCode()确定,get()是名称的长度。如果名称的长度不同,则桶(希望)会有所不同,因此#1将找不到匹配的条目。这解释了get():相同的对象,但是在put和get之间更改了哈希码,因此可以在不同的桶中查找。

现在,一旦找到合适的存储桶,equals()将查看存储桶中的密钥并使用#3进行比较,因为可以将多个密钥放在同一个存储桶中。这解释了equal():相同的存储桶,但对象不是#2equal()是同一个存储桶,对象是equal(),因为名称是<table datatable="ng" dt-options="datatable.dtOptions" dt-column-defs="datatable.dtColumnDefs"> <thead> <tr> <th></th> <th>ID</th> <th>Comuna</th> <th>Proyecto</th> </tr> </thead> <tbody> <tr ng-repeat="doc in json"> <td>a</td> <td>b</td> <td>c</td> <td>d</td> </tr> </tbody> </table>

答案 1 :(得分:1)

Hashcode值是正确的,等于8.不应该是你建议的6。 您正在更改d1指向的名称值 在制作d1.name =“magnolia”时;

在步骤1,由于哈希码函数名称,它为null,并且在hashmap中找不到“magnolia”哈希索引。)

重要说明:地图使用哈希码和等号。 hashcode用于在hashmap中查找您要查找的对象。找到此对象时,将调用equals以确保它们确实与您期望的相同(值)。 您的哈希码应该是唯一的。想想如果你有不同的名字和相同的长度会怎么样。 另外,请确保函数名称为hashCode,等于并覆盖它们。

我不知道为什么你的hashcode是基于lenght的,但我建议你使用HashCodeBuilder()和EqualsBuilder()。