equals方法
public boolean equals(Object obj)
指示其他某个对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:
- 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
- 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
- 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
- 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
- 对于任何非空引用值 x,x.equals(null) 都应返回 false。Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
参数:
obj - 要与之比较的引用对象。
返回:
如果此对象与 obj 参数相同,则返回 true;否则返回 false。
实现高质量equals方法的诀窍
- 使用==操作符检查“参数是否为这个对象的引用”。
- 使用instanceof操作符检查“参数是否为正确的类型”。
- 把参数转换为正确的类型。
- 对于该类中的每个“关键(significant)”域,检查参数中的域是否与该对象中对应的域想匹配。
- 当你编写完成了equals方法之后,应该问自己三个问题:它是否是对称的、传递的、一致的?
一些告诫
- 覆盖equals时总要覆盖hashCode。
- 不要企图让equals方法过于智能。
- 不要将equals声明中的Object对象替换为其他的类型。
hashCode方法
public int hashCode()
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
返回:
此对象的一个哈希码值。
几点注意
- 要想使hashCode()实用,它必须速度快,并且必须有意义。也就是说,它必须基于对象的内容生成散列码。散列码不必是独一无二的(应该关注生成速度,而不是唯一性),但是通过hashCode()和equals(),必须能够完全确定对象的身份。
- 散列表的生成范围并不重要,只要是int就好
- 好的hashCode()应该生成均匀分布的散列码。如果散列码都集中在一块,那么hashMap后者hashSet在某些区域的负载会很重,这样就不如分布均匀的散列函数快。
如何生成一份像样的hashCode():
- 给int变量result赋予某个非零常量
- 为对象每个有意义的域f(即每个可以做equals操作的域)计算出一个int散列码c
- 合并计算得到的散列码 result= 31*result+c;
- 返回result
- 检查hashCode()最后生成的结果,确保相同的对象有相同的散列码