我正在努力深入理解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
答案 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));
}
}