每天学一点 面试题 1 ,HashCode与 equals。

hashcode 和 equals的区别

1.如果两个对象的hashcode相等,那么这两个对象相等吗?
不一定相等
hashcode()方法是实际上返回的就是对象存储的物理地址(实际可能并不是)
比如:
String s1 = new String(”1“);
String s2= new String(”1“);
那么s1.hashCode() 是等于 s2.hashCode()的。

2.如果两个对象的equals相等,那么这两个对象相等吗?
不一定相等。
如果没有重写equals()时候,那么会继承Object里面的equals() 代码如下。

 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;
}

不难看出,当String对象时候Object里面的方法判断了字符是否相等,相等就返回true;所以一般需要使用equals时候最好重写。

   public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    }

3.这里我们首先要明白一个问题:
equals()相等的两个对象,hashcode()一定相等;
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。

mport java.util.*; 
public class HashSetTest 
{ 
 public static void main(String[] args) 
  { 
             HashSet hs=new HashSet(); 
             hs.add(new Student(1,"zhangsan")); 
             hs.add(new Student(2,"lisi")); 
             hs.add(new Student(3,"wangwu")); 
             hs.add(new Student(1,"zhangsan")); 

             Iterator it=hs.iterator(); 
             while(it.hasNext()) 
             { 
                    System.out.println(it.next()); 
             } 
 } 
} 
class Student 
   { 
 int num; 
 String name; 
 Student(int num,String name) 
            { 
            this.num=num; 
             this.name=name; 
             } 
          public String toString() 
            { 
                return num+":"+name; 
             } 
       }      

输出结果为:
1:zhangsan
1:zhangsan
3:wangwu
2:lisi

问题出现了,为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有
因为在根据hashcode()对两次建立的new Student(1,“zhangsan”)对象进行比较时,生成的是不同的哈希码值,所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。那么为什么会生成不同的哈希码值呢?上面我们在比较s1和s2的时候不是生成了同样的哈希码吗?原因就在于我们自己写的Student类并没有重新自己的hashcode()和equals()方法,所以在比较时,是继承的object类中的hashcode()方法,呵呵,各位还记得object类中的hashcode()方法比较的是什么吧!!

它是一个本地方法,比较的是对象的地址(引用地址),使用new方法创建对象,两次生成的当然是不同的对象了(这个大家都能理解吧。。。),造成的结果就是两个对象的hashcode()返回的值不一样。所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。那么怎么解决这个问题呢??
答案是:在Student类中重新hashcode()和equals()方法。

public int hashCode() 
{ 
        return 	name.hashCode(); 
} 

【原则】按照equals( )中比较两个对象是否一致的条件用到的属性来重写hashCode()。

{1}. 常用的办法就是利用涉及到的的属性进行线性组合。

{2}. 线性组合过程中涉及到的组合系数自定义即可。

注意,拼接之后的数值不能超过整形的表达范围。

{3}. 公式:属性1的int形式+ C1属性2的int形式+ C2属性3的int形式+ …

猜你喜欢

转载自blog.csdn.net/qq_34243849/article/details/84851675