java中equal方法和hashCode的理解
2015-11-09 14:55
846 查看
第一:两个都是Object的通用方法。
第二:Java语言对equals()的要求如下,这些要求是必须遵循的:
• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。• 反射性:x.equals(x)必须返回是“true”。
• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
• 还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
• 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
下面是String.java中equals的方法
/** * Compares this string to the specified object. The result is {@code * true} if and only if the argument is not {@code null} and is a {@code * String} object that represents the same sequence of characters as this * object. * * @param anObject * The object to compare this {@code String} against * * @return {@code true} if the given object represents a {@code String} * equivalent to this string, {@code false} otherwise * * @see #compareTo(String) * @see #equalsIgnoreCase(String) */ public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
第三:hashCode的规则
1.在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。2.如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
3.实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
下面是String.java中的hashCode函数
/** * Returns a hash code for this string. The hash code for a * <code>String</code> object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using <code>int</code> arithmetic, where <code>s[i]</code> is the * <i>i</i>th character of the string, <code>n</code> is the length of * the string, and <code>^</code> indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
第四:《Effective Java》中提出了一种简单通用的hashCode算法
1. 初始化一个整形变量,为此变量赋予一个非零的常数值,比如int result = 17;2. 选取equals方法中用于比较的所有域,然后针对每个域的属性进行计算:
(1) 如果是boolean值,则计算f ? 1:0
(2) 如果是byte\char\short\int,则计算(int)f
(3) 如果是long值,则计算(int)(f ^ (f >>> 32))
(4) 如果是float值,则计算Float.floatToIntBits(f)
(5) 如果是double值,则计算Double.doubleToLongBits(f),然后返回的结果是long,再用规则(3)去处理long,得到int
(6) 如果是对象应用,如果equals方法中采取递归调用的比较方式,那么hashCode中同样采取递归调用hashCode的方式。否则需要为这个域计算一个范式,比如当这个域的值为null的时候,那么hashCode 值为0
(7) 如果是数组,那么需要为每个元素当做单独的域来处理。如果你使用的是1.5及以上版本的JDK,那么没必要自己去重新遍历一遍数组,java.util.Arrays.hashCode方法包含了8种基本类型数组和引用数组的hashCode计算,算法同上,
============================测试程序============================
import java.util.HashSet; public class NMMain { public static void main(String[] args) { // TODO Auto-generated method stub HashSet<NMObject> nmHS = new HashSet<NMMain.NMObject>(); NMObject nmObject1 = new NMObject(); nmObject1.m = 10; nmObject1.n = 8; NMObject nmObject2 = new NMObject(); nmObject2.m = 10; nmObject2.n = 8; NMObject nmObject3 = new NMObject(); nmObject3.m = 8; nmObject3.n = 10; nmHS.add(nmObject1); nmHS.add(nmObject2); nmHS.add(nmObject3); } public static class NMObject{ public int n; public int m; @Override public boolean equals(Object obj) { // TODO Auto-generated method stub if(!(obj instanceof NMObject)){ return false; } return n == ((NMObject)obj).n && m == ((NMObject)obj).m; } @Override public int hashCode() { // TODO Auto-generated method stub return n+m; } } }
nmHS中有两个对象,因为NMObject中覆盖了equals和hashCode的方法,nmObject1和nmObject2中n,m值相等所以两者被认为是同一个对象。而nmObject3虽然hash值相同但是他们equals方法不相等,所以认为是不同的对象。
判断相等的规则:
条件一:判断hashCode是否相等,如果不相等就证明了两个对象不相等;如果相等进入“条件二”
条件二:判断equals是否相等,如果不相等就证明两个对象不相等;如果相等就证明是真的不相等啦
相关文章推荐
- Java阻塞IO与非阻塞IO
- Java 字符串比较 .equals, ==
- springSecurity理解一 一个简单的HelloWorld
- springmvc put请求无法解析请求体参数解决办法
- java字符串截取
- Java线程池使用说明
- Struts2中使用Validation数据验证
- Java 工厂方法模式
- Java线程池源码解析及高质量代码案例
- 使用SpringMvc调用POI jar导出excel的源码
- Java记录 -73- 泛型详解
- java集合的概述
- Java中的简单工厂模式
- 获取Spring 注入容器、(注解的也可以获取bean)
- eclipse中如何修改不同后缀文件类型的编码
- JavaSript面向对象
- java.lang.outofMemoryError解决方法
- Jecc(java椭圆曲线加密库)学习笔记及ECDH实现
- Google Java编程风格指南中文版
- java.lang.IllegalArgumentException: taglib definition not consistent with specification version