我很困惑哈希码和等于怎么样 - 为什么用相同参数创建的两个对象彼此不相等?

时间:2018-05-10 19:52:42

标签: java object equals hashcode

我正在努力深入理解Java,我正在尝试比较相同的对象。

我创建了两个具有相同值的字符串对象,但分配给了不同的变量。事实证明它们具有相同的哈希码。

之后我创建了表示person的简单类,并创建了此类的两个实例,并将相同的参数传递给构造函数。原来他们有不同的哈希码。

现在我很困惑它是如何运作的。你能解释一下吗?

我的代码:

 public static class Person {

        public String name;
        public String lastName;

        public Person(String name, String lastName) {
            this.name = name;
            this.lastName = lastName;
        }
    }

    public static void main(String[] args) {

        String s1 = new String("foo");
        String s2 = new String("foo");
        System.out.println("String1 hashcode: " + s1.hashCode());
        System.out.println("String2 hashcode: " + s2.hashCode());
        System.out.println("Is String1 equal to String2?: " + s1.equals(s2));

        Person p1 = new Person("John", "Doe");
        Person p2 = new Person("John", "Doe");
        System.out.println("Person1 hashcode: " + p1.hashCode());
        System.out.println("Person2 hashcode: " + p2.hashCode());
        System.out.println("Is Person1 equal to Person2?: " + p1.equals(p2));

    }
}

我的输出:

String1 hashcode: 101574
String2 hashcode: 101574
Is String1 equal to String2?: true
Person1 hashcode: 325040804
Person2 hashcode: 1173230247
Is Person1 equal to Person2?: false

2 个答案:

答案 0 :(得分:9)

hashCode method in String仅根据字符串的内容计算哈希码。

  

返回此字符串的哈希码。 String对象的哈希码计算为

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

但是,您尚未在hashCode中声明Person方法,因此它会继承that method from Object

  

尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数。

如果一个类没有覆盖hashCode,那么我们应该期望不同对象的不同哈希码,而不管对象的内容如何。

String一样,您可以定义自己的hashCode方法,该方法仅根据其内容确定Person哈希码。

您还应该覆盖equals(Object),以便Person类定义Person个实例彼此相等的方式;必须始终如一地定义这两种方法:

  

hashCode的一般合约是:

     
      
  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
  •   
  • 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
  •   
  • 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须生成不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。
  •   

答案 1 :(得分:0)

String internal Class具有强大的hashcode和equals实现,因此当你创建两个具有相同内存地址的String实例并检查hashcode时它会返回相同的hash。

但是你实现的类Person没有继承java.lang.Object实现的hashcode和equals来检查两个对象是否相同。

通过覆盖java.lang.Object哈希码和equals方法实现,更新了以下代码供您参考。这应该会返回预期的结果。

public static class Person {
    public String name;
    public String lastName;

    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, lastName);

    }

    @Override
    public boolean equals(Object obj) {
        if(obj==null || !(obj instanceof Person))
           return false;
        Person u=(Person) obj;
        return u.name.equals(name) && u.lastName.equals(lastName);
    }
}

public static void main(String[] args) {

    String s1 = new String("foo");
    String s2 = new String("foo");
    System.out.println("String1 hashcode: " + s1.hashCode());
    System.out.println("String2 hashcode: " + s2.hashCode());
    System.out.println("Is String1 equal to String2?: " + s1.equals(s2));

        Person p1 = new Person("John", "Doe");
        Person p2 = new Person("John", "Doe");
        System.out.println("Person1 hashcode: " + p1.hashCode());
        System.out.println("Person2 hashcode: " + p2.hashCode());
        System.out.println("Is Person1 equal to Person2?: " + p1.equals(p2));

    }
}