优秀的编程知识分享平台

网站首页 > 技术文章 正文

C++涨知识:equals 和 == 你真的了解吗?

nanyue 2024-07-26 15:37:22 技术文章 16 ℃

基本概念

==是运算符,比较的是两个变量是否相等;

equals()是Object方法,用于比较两个对象是否相等

看一下源码:

复制代码

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;

}

复制代码

当this==anObject的时候,返回true,即this 和 obj引用同一个对象时,才会返回true;

还有就是当判断字符串相等的时候,当anObject是String类型,并且长度和内容一样的时候,返回true;

小结

只有当引用一个对象的时候,才会返回true。

而我们在实际用equals()方法的时候,我们往往不是为了判断两个引用的是一个对象,因此我们此时要重写equals()方法;

equals()有以下的公约必须遵守:

对称性:x,y非空,如果x.equals(y)返回true,那么y.equals(x)必为true;

自反性:对于任何非null的引用值x,x.equals(x)必须返回true;

传递性:x,y,z非空,x.equals(y),y.equals(z)返回true,那么x.equals(z)必为true;

一致性:x,y非空,只要对象信息没有被修改,那么多次调用x.equals(y)的结果肯定都一样;

对于任何非null的引用值x,x.equals(null)必须返回false;

因此,我们一般有以下推论:

任何情况下,x.equals(null),永远返回是false;x.equals(和x不同类型的对象)永远返回是false。

equals()相等的两个对象,hashcode()一定相等;反过来:hashcode()不等,一定能推出equals()也不等;

hashcode()相等,equals()可能相等,也可能不等

现在我们可以这样解释了:

1、因为是按照hashCode来访问小内存块,所以hashCode必须相等。

2、HashMap获取一个对象是比较key的hashCode相等和equal为true。

3、比如对象ObjectA和ObjectB他们都有属性name,那么hashCode都以name计算,所以hashCode一样,但是两个对象属于不同类型,所以equal为false。所以hashCode相等,却可以equal不等

当我们编写完成了equals()方法的时候,我们要问自己三个问题:它是否是对称的、传递的、一致的;

问题:重写equals()方法的时候总要重写hashcode()方法,为什么要重载equal方法?

在每个重写equals()的类中,我们必须重写hashcode()方法;如果不这样做,会违反hashcode()的公约:

1.只要对象的信息没有改变,那么对一个对象调用多次,hashcode()方法都必须始终如一的返回同一个整数;

2.如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashcode()方法都必须产生同样的结果;

3.如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashcode()方法不一定产生同样的结果;

相等的对象必须有相同的散列码

代码示例

复制代码

import java.util.HashSet;

import java.util.Set;

/**

* hashcode和equals方法

* HashMap中有一个put方法,put(key,value)key是无序不可重复的

*/

public class SetTest2 {

public static void main(String[] args)

{

//创建集合

Set es = new HashSet();

Employee e1 = new Employee("1000","tao");

Employee e2 = new Employee("1000","tao");

// Employee e2 = new Employee("1001","tao1");

Employee e3 = new Employee("1002","tao2");

Employee e4 = new Employee("1003","tao3");

Employee e5 = new Employee("1004","tao4");

Employee e6 = new Employee("1005","tao5");

// System.out.println(e1.equals(e2));

// System.out.println(e2);

System.out.println(e1.hashCode());

System.out.println(e2.hashCode());

es.add(e1);

es.add(e2);

es.add(e3);

es.add(e4);

es.add(e5);

es.add(e6);

System.out.println(es.size());

}

}

class Employee{

String num;//员工编号

String name;

Employee(String num,String name){

this.num = num;

this.name = name;

}

//重写equals方法,如果员工编号相同并且名字相同,则是同一个对象

public boolean equals(Object o){

if (this == o){

return true;

}

if (o instanceof Employee){

Employee e = (Employee) o;

if (e.num.equals(this.num) && e.name.equals(this.name))

{

return true;

}

}

return false;

}

//重写Hashcode方法

public int hashCode(){

//以员工编号分组,可散列均匀分布

return num.hashCode();

}

}

hashCode()的底层实现:

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;

}

复制代码

可以看到最终hash = s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1];

最后你觉得我们的文章对你有帮助,欢迎关注我,可以私信我:久伴,领取学习资料,在评论下方可以关注我的学习群,你可以随时在上面向我们提问,把你在学习C++过程中所遇到的问题发给我们。我们每天都会按时回复大家的每一个问题,希望久伴可以伴随你从入门到专家

Tags:

最近发表
标签列表