简单来说hashCode的原理是将一个对象映射成一个整数,这个整数可以作为该对象的标识符。如果两个对象的hashCode相同,则可以认为它们是相同的对象。Java中hashCode的实现是将对象的内存地址转换成一个整数值。 equals的原理是用来比较两个对象是否相等。如果两个对象相等,则它们的hashCode也必须相等。Java中equals的实现是先比较两个对象的内存地址,如果相等则返回true,否则再比较两个对象的属性是否相等。
hashCode详解
hashCode()是Java中Object类中的一个方法,用于返回对象的哈希码(散列码),也就是将一个对象转换成一个整数。hashCode()方法的签名如下:
public int hashCode()
hashCode()方法返回的哈希码是一个int类型的整数,与对象的内存地址有关,不同的对象的哈希码通常不同。但也有可能出现相同的哈希码,这种情况称为哈希码冲突。 在Java中,哈希码通常用于散列表(HashMap、HashSet等)的实现。散列表是一种以键值对形式存储数据的数据结构,它的基础是哈希函数,即将键映射成一个索引,从而可以快速地查找对应的值。 Object类中的hashCode()方法的实现是将对象的内存地址转换成一个整数值。因此,如果两个对象的内存地址不同,那么它们的哈希码也不同。但如果两个对象的内存地址相同,它们的哈希码也相同。这种情况下,需要重写hashCode()方法,以确保不同的对象有不同的哈希码。 hashCode()方法的重写需要遵循以下规则:
- 如果两个对象相等,则它们的哈希码必须相等。
- 如果两个对象的哈希码相等,它们不一定相等。因此,hashCode()方法的重写需要在equals()方法一起重写,以确保两个对象相等时它们的哈希码也相等。 在重写hashCode()方法时,可以使用对象的字段计算哈希码,例如:
public int hashCode() {
int result = 17;
result = 31 * result + field1;
result = 31 * result + field2;
return result;
}
其中,31是一个奇素数,用于确保哈希码的唯一性。将result初始化为一个非0的奇数,然后将result与31相乘后加上对象的字段值,这样可以保证不同的对象有不同的哈希码。
equals详解
equals()方法是Java中Object类中的一个方法,用于比较两个对象是否相等。equals()方法的签名如下:
public boolean equals(Object obj)
equals()方法需要重写,以便在自定义类中正确地比较两个对象是否相等。在重写equals()方法时,需要遵循以下规则:
- 自反性:对于任意非null的引用值x,x.equals(x)应该返回true。
- 对称性:对于任意非null的引用值x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。
- 传递性:对于任意非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,则x.equals(z)也应该返回true。
- 一致性:对于任意非null的引用值x和y,在对象中没有改变的情况下,多次调用x.equals(y)应该返回相同的结果。
- 对null的比较:对于任意非null的引用值x,x.equals(null)应该返回false。 在重写equals()方法时,通常需要比较对象的属性是否相等。例如:
public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; if (this.getClass() != obj.getClass()) return false; MyClass other = (MyClass) obj; if (this.field1 != other.field1) return false; if (!this.field2.equals(other.field2)) return false; return true; }
在这个例子中,首先检查传入的对象是否为空,是否是同一个对象,是否是同一个类的实例。然后比较对象的属性是否相等,如果所有属性都相等,则返回true,否则返回false。 需要注意的是,如果一个类重写了equals()方法,也应该重写hashCode()方法,以确保两个相等的对象具有相同的哈希码。因为在散列表(例如HashMap)中,哈希码是用于查找对象的,如果两个相等的对象具有不同的哈希码,可能会导致散列表无法正确地查找对象。