public int hashCode()
hashCode
method must consistently return the same integer, provided no information used in equals
comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. equals(Object)
method, then calling the hashCode
method on each of the two objects must produce the same integer result. equals(java.lang.Object)
) method, then calling the hashCode
method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables. 大概意思:
对于基本数据类型,比较值
对于引用数据类型,比较地址
public boolean equals(Object obj)
特性:自反性、对称性、传递性、一致性、非空值与空值比较返回false
具体实现要看该对象是怎么实现的
equals
的定义 The equals
method for class Object
implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x
and y
, this method returns true
if and only if x
and y
refer to the same object ( x == y
has the value true
).
看源码就能理解他的意思,也就是直接比较两个对象的内存地址。
public boolean equals(Object obj) { return (this == obj); }
equals
方法来进行其他对象的比较。 比如Integer,比较值
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
比如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; }
比如自定义的User
public class User { private String id; private String name; }
如果你不重写,他还是继承Object的equals方法实现,也就是比较两个对象的内存地址。
@Override public boolean equals(Object obj) { return super.equals(obj); }
返回结果,既然是两个不同的对象,那么其内存地址自然不相等。
重写后(比较各字段值)
@Override public boolean equals(Object obj) { if (obj == this) return true; // 判断obj对象是否是User的引用 if (obj instanceof User) { // 检查obj是否为正确的类型 User user = ((User) obj); // 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配 return user.id.equals(id) && user.name.equals(name); } return false; }
返回结果
回忆一下hashcode原则的第二条:
If two objects are equal according to the equals(Object)
method, then calling the hashCode
method on each of the two objects must produce the same integer result.
equals结果相等,两者的hashCode也应该相同。
且我们知道, 集合类判断对象是否相等的两个条件:1.equals结果返回true;2.两者返回的hashCode值相同
因此重写equals的同时,也应该重写hashCode方法
比较未重写hashCode的User对象的hashCode
重写后
@Override public int hashCode() { return id.hashCode() + name.hashCode(); }
返回结果
instanceof
操作符检查参数是否为正确的类型 对于类中的 关键属性 ,检查参数传入对象的属性是否与之相匹配;
user.id.equals(id) && user.name.equals(name)
JDK7及以上,调用Objcects.equals比较: Objects.equals(id, user.id) && Objects.equals(name, user.name)
原理相同
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
你可以自定义,也可以选择其他有效的方式。
但是自定义的不一定高效,且要保证: 如果你在重写时用到了对象类型,那么你也要同时保证被引用对象也已经重写了hashCode方法 ,否则每次得到的他的HashCode不一定相同,从而影响到当前对象返回的hashCode值。
摘自
@Override public int hashCode() { // Classic Way int result = 17; result = 31 * result + (id == null ? 0 : id.hashCode()); result = 31 * result + (name == null ? 0 : name.hashCode()); return result; }
@Override public int hashCode() { // JDK7 return Objects.hash(id, name); }
其实他的原理也是一样的
@Override public static int hashCode(Object a[]) { if (a == null) return 0; int result = 1; for (Object element : a) result = 31 * result + (element == null ? 0 : element.hashCode()); return result; }
这种没尝试过
@Override public int hashCode() { return new HashCodeBuilder(17, 37) .append(id) .append(name) .toHashCode(); }
选取equals方法中用于比较的所有域,然后针对每个域的属性进行计算: