基于传递的字符串长度的哈希码方法实现

Hashcode method implementation based on length of the string passed

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

根据上面的程序,它说:

上面三行说的是name的长度和hashcode()相关的实现,但是调用get()方法时如何比较长度呢?

Hashcode 值正确,等于 8。不应如您建议的那样为 6。 您正在更改 d1 指向的名称值 当 d1.name = "magnolia";

在第 1 步,由于 hashcode 函数名称,它为 null,并且在 hashmap 中找不到 "magnolia" 哈希索引。)

重要提示:地图适用于哈希码和等号。 hashcode 用于在 hashmap 中查找您要查找的对象。找到此对象后,将调用 equals 以确保它们确实与您期望的(值)相同。 您的哈希码应该是唯一的。想一想如果您必须使用相同长度的不同名称怎么办。 此外,确保函数名称是 hashCode,等于并覆盖它们。

我不明白为什么你的哈希码是基于长度的,但我建议你使用 HashCodeBuilder() 和 EqualsBuilder()。

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

编辑:并回答 "how is it comparing the length when get() method is called?":

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

get() 会先找桶。存储桶由名称的长度 hashCode() 决定。如果名字的长度不一样,bucket 会(希望如此)不同所以 get() 将找不到匹配的条目。这解释了 #1:相同的对象,但哈希码在 put 和 get 之间发生了变化,因此 get 看起来在不同的桶中。

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