equals和hashcode方法


1."=="和equals的区别

  ==的操作符生成的是一个boolean类型的结果,比较的是两个数值之间的关系或者对象的引用是否相等。equals的本意是判断两个对象的内容是否相等,但一般判断的时候分两种情况。

  在Java中有八种基本的数据类型,对于这八种的基本数据类型,变量在存储的时候是直接存储的值,所以在用==来比较这些基本数据类型时候,比较的是变量的值是否相等,对于下面的程序,我们都知道返回的是true和false。

int a=1;
int b=1;
int c=2;
System.out.println(a==b);
System.out.println(a==c);</span>
  在Java中,引用类型的变量存储的并不是值本身,而是与其关联的对象在内存中的地址,所以当==操作引用型的变量时候,比较的是两边的对象的引用是否相同,即内存地址。对于下面的程序,将会输出true和false。
Student stu1=new Student("A",12);
Student stu2=stu1;
Student stu3=new Student("B",12);
System.out.println(stu1==stu2);
System.out.println(stu1==stu3);
  总结,对于==操作符而言,如果比较的基本数据类型,则直接比较值即可,如果比较的是引用型数据类型则比较的是内存中的地址是否相同。

  equals方法是Java中Object类的一个方法,在Object类中是这样定义equals方法的

 public boolean equals(Object obj) {
	return (this == obj);
    }
  可以看到在Object中,equals的作用和==是一样的,但是我们知道对于下面的程序来说,输出为true。
String a="Hello";
String b="Hello";
System.out.println(a.equals(b));
  这是为什么呢,因为在String类中重写了equals方法
public boolean equals(Object anObject) {
	if (this == anObject) {
	    return true;
	}
	if (anObject instanceof String) {
	    String anotherString = (String)anObject;
	    int n = count;
	    if (n == anotherString.count) {
		char v1[] = value;
		char v2[] = anotherString.value;
		int i = offset;
		int j = anotherString.offset;
		while (n-- != 0) {
		    if (v1[i++] != v2[j++])
			return false;
		}
		return true;
	    }
	}
	return false;
    }
  从重写的方法中可以看到,首先判断对象的引用是否相同,再判断比较的对象是否内容一致,如果一致的话就比较二者的内容是否相同,所以对于上述的程序,输出为true就不奇怪了。在Java中,所有的内置类的equals方法都是这样的。

  还是上面的例子接着看下面的代码:

Student stu1=new Student("A",12);
Student stu2=stu1;
Student stu3=new Student("A",12);
System.out.println(stu1.equals(stu2));
System.out.println(stu1.equals(stu3));
  上述的输出为true和false,因为在Student类中没有重写equals方法,所以在用equals方法比较stu1和stu2 的时候比较的是引用,在比较stu1和stu3时候还是引用,因为后两者指向的对象在内存中的地址不一样,所以结果就是false,但是stu1和stu3很显然是两个一样的Student,内容是一样的,所以在用equals进行比较时候,希望返回的true。

  因此我们就需要在定义的Student类的时候重写equals方法,这样在使用equals方法的时候比较的就是两者的内容是否相同了。

	public boolean equals(Object o){
		if (o==null){
			return false;
		}
		if(o==this){
			return true;
		}
		
		if(getClass()!=o.getClass()){
			return false;
		}
		Student s=(Student)o;
		return (this.getId()==s.getId());
	}
		
}
  重写了equals方法之后,再进行比较的值为true

2.Hashcode和equals

  在Java中的Hashcode方法也是有Object类定义的,该方法会针对不同的对象返回一个不同的整数。Hashcode方法主要应用于散列表中。在程序运行期间,如果根据equals方法判断两个对象时相等的,那么这两个对象的hashcode方法的返回值肯定也是要相等的。

  我们知道在Java中引用到Hash表的地方有集合中的Hashset,HashMap和HashTable

在Set中不允许元素相同,Map中不允许键值相同。如果在集合中插入1000个元素,再插入1001个元素的时候要一个个的进行比较吗,如果是这样的话,那么集合的效率也太低了,这里用到了哈希表,在进行元素插入时候,先根据插入的元素计算对应的hash值,根据hash值可以直接定位到元素在hash表中的位置 ,然后从该位置向后在链表中进行查找,这样可以提高插入和查询的效率。

  所以如果利用equals方法比较两个元素的结果为true的话,那么二者的hashcode方法返回值也要是一样的,如果equals方法返回的值是false,那么二者的hashcode方法返回值可以相同也可以不相同,如果hashcode值不同,那么二者的equals方法肯定是false。hashcode值得结果只能决定元素在hash表中的位置。

  如果我们在没有覆写hashcode的方式下将两个内容相同的对象插入到Hashset中,查看输出的效果(已经覆写了equals方法):

Student stu1=new Student("A",12);
Student stu2=stu1;
Student stu3=new Student("A",12);
System.out.println(stu1.equals(stu2));
System.out.println(stu1.equals(stu3));
		
HashSet<Student> s=new HashSet<Student>();
s.add(stu1);
s.add(stu3);
System.out.println(s.size());</span>
  上面程序的结果输出如下:

  可以看到,集合的大小为2,但插入的两个元素明明是一样的,我们希望在这种情况下集合的大小因该是1,此时就需要覆写hashcode方法了。

public  int hashCode(){
   return name.hashCode();
}</span>
  此时的输出结果为:


  因为在没有覆写hashcode方法之前,默认调用的是本地的hashcode方法,此时计算的两者的hashcode值是不一样的,所以在hash表中的位置也就是不一样的,所以就可以插入两个,但覆写hashcode方法之后,二者计算得到的hashcode值是一样的,所以在插入进行判断的过程中就会判断两者的内容是否一样,最后结果为1.因此一旦重写了equals方法,就必须要重写hashcode方法。
   




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值