java - 我很困惑 hashcode 和 equals 如何工作 - 为什么使用相同参数创建的两个对象彼此不相等?
问题描述
我正在努力更深入地了解 Java,并尝试比较相同的对象。
我创建了两个具有相同值但分配给不同变量的字符串对象。事实证明,它们具有相同的哈希码。
之后,我创建了代表人的简单类,并创建了这个类的两个实例,并将相同的参数传递给构造函数。原来他们有不同的哈希码。
现在我很困惑它是如何工作的。你能解释一下吗?
我的代码:
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
解决方案
中的hashCode
方法String
仅根据字符串的内容计算它的哈希码。
返回此字符串的哈希码。对象的哈希码
String
计算为s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
但是,您尚未在 中声明hashCode
方法Person
,因此它从Object
.
在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。
如果一个类没有 override hashCode
,那么我们应该期望不同的对象有不同的哈希码,而不管对象的内容如何。
就像String
,您可以定义自己的方法,该方法仅根据其内容hashCode
确定的哈希码。Person
您还应该重写equals(Object)
,以便Person
该类定义Person
实例如何彼此相等;这两种方法的定义必须一致:
hashCode 的一般合约是:
- 每当在 Java 应用程序执行期间对同一个对象多次调用它时,hashCode 方法必须始终返回相同的整数,前提是没有修改对象上的 equals 比较中使用的信息。该整数不需要从应用程序的一次执行到同一应用程序的另一次执行保持一致。
- 如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。
- 如果根据 equals(java.lang.Object) 方法,如果两个对象不相等,则不需要对两个对象中的每一个调用 hashCode 方法都必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。
推荐阅读
- sql - 在 PostgreSQL 中创建触发器
- file - 如何用 Rust 创建二进制文件?
- c# - 在 aspx 网页中从后面调用函数
- python - 包含字母和整数的 Python 列表
- database - DB Sharding:数据迁移到另一台机器
- python - Numpy 将 where 操作应用于图像的特定索引范围
- google-apps-script - 除某些单元格外,自动复制和保护工作表
- javascript - JavaScript 是否支持构造函数重载概念?
- swift - Swift:仅从 NSUserDefaults 中删除第一个对象
- javascript - express.js 响应值为破坏