java - 根据传递的字符串长度实现Hashcode方法

标签 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 和 berts 的 SCJP6 书中的 hashcode() 实现。虽然我对哈希码实现有基本的了解,但书中的一个场景欺骗了我,我对输出感到困惑。

根据上面的程序,它说:

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

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

最佳答案

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
    }
}

编辑:并回答“调用 get() 方法时如何比较长度?”:

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

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

现在,一旦找到合适的存储桶,get() 将查找存储桶中的键,并使用 equals() 进行比较,因为有多个键可以放在同一个桶里。这解释了#3:相同的存储桶,但对象不是equal()#2 是同一个存储桶,并且对象是 equal(),因为名称是 equal()

关于java - 根据传递的字符串长度实现Hashcode方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30059816/

相关文章:

java - 尝试从主方法运行 TestNG 时无法在类路径中找到类

Java Throw-Catch 异常困惑-1 示例

java - SCJP 书中与集合相关的逻辑

JavaScript 日期转换为错误的 Java 日期

java - 在 GAE 中保留数据 - 实体不能有长主键并且不能是子对象

java - 我如何知道我的服务何时从广播接收器与 Android 调用?

java - Scala (java) grpc 异步拦截器状态传播

java - SCJP程序给出输出8 2怎么办?

java - 为什么我们需要一个静态锁来同步system.out.println()?

缩小原始转换期间的 Java 编译器行为