equals在我们代码经常看到,用来比较值或者对象是否相等,有时我们还用 "==" 这个符号来比较。我们知道 "==" 符号是指对内存地址进行比较,而equals除了比较地址还比较值,我们来看下equals源码。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = length();
if (n == anotherString.length()) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
我们可以很清晰的看出,equals这个方法,第一步就是比较两个变量地址,如果地址是同一个,那就表示他们相同。如果不相同,那就看他们是不是String类型,如果是的话,就比较他们字符串是否相同。
从这也能看出,我们在比较两个变量时,不管是String还是其他类型变量,用equals比较合适。
上面代码我们可以看到,不同内存地址的两个对象不可能相等,哪怕这两个对象数据一样。我们来个实例。
这两个Person相等吗?看上面equals源码,不相等。但是按照现实,他们身份证Id相同、名字相同、年龄一样,那就是同一个人哈。
这个时候我们就要重写equals方法了。我们不应该比较他们内存地址,而是比较他们内部字段数据,身份证Id、名字、年龄。代码如下。
@Override
public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object obj) {
if(obj==null)
return false;
if(this==obj)
return true;
if(obj instanceof Person){
Person objTemp=(Person)obj;
if(objTemp.Id.equals(this.Id)&&objTemp.name.equals(this.name)&&objTemp.age.equals(this.age))
return true;
}
return false;
}
这里就是简单写一下,清楚意思就好。
这样我们才能判断两个Person是不是相同。
上面我们清楚了为什么以及如何重写equals,但是这里有个注意点,那就是hashCode。在我们存储变量数据时,hashCode是一个很重要的判断比较的标准,比如HashSet,有兴趣的同学可以看下这篇文章。当我们把Person变量存储在HashSet的时候,HashSet会对变量hashCode进行比较,我们来看下HashSet源码片段
这个是HashMap中的putVal源码,hashSet.add方法最终会调用此方法。我们可以看到红框代码,如果hash表中原有的变量hash值和新增的变量hash值一样,那就直接替换旧值。
如果hashCode不重写,每个Person即使内部数据一样,但是hash值不一样,在同一个hashset表中,就会出现重复存储。这个时候我们就要重写hashCode方法,让内部数据一样的Person的hashCode也一样。
hashCode方法重写和equals差不多
@Override
public int hashCode() {
int result = 10;
result = 31 * result + (Id == null ? 0 : Id.hashCode());
result = 31 * result + (name == null ? 0 : name.hashCode());
result = 31 * result + (age == null ? 0 : age.hashCode());
return result;
}
}
result=10是随便取值的,就是一个简单初始值,没有其他含义。
31这个值,是参考String hashCode源码中取的值,这个值,网上有各种解析和猜测,可以网上查查。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。