小白过来看!!!java的==和equals()方法一样嘛?equals()和hashCode()到底有何联系?

3 篇文章 0 订阅
1 篇文章 0 订阅

很多人都知道对象a,对象b     a==b比较的是两者之间的内存地址,a.equals(b)=true 比较的是a与b的字符串内容。

但其实单单只知道这些只能说是初学者必须知道的东西,下面根据我浅薄的知识来给小白们扩充扩充,当然,欢迎大佬们来补充,我还有很多需要学习的地方,若有不对的地方,请各位帮忙指出,谢谢大家!!

具体的说,对于基本类型来说==比较的是两者的值,对于对象类型==比较的是内存地址。

         int a=1;
        int b=1;
        Integer c=new Integer(2);
        Integer d=new Integer(2);
        System.out.println(a==b);//返回true

        System.out.println(c==d);//返回false

 

equals():

 

为了更好的引申出equals方法,在这里我定义了一个类部类User,通过new出两个实例来比较

java的equals()方法,我们可以从源码得知equals()存在Object类,因为Object类是所有类的直接或间接的父类,所以我们可以知道equals()继承自Object类,通过源码我们可以看出,equals()的底层方法依赖的是==(可以参考下图1),也就是equals()原始方法与==是相同的,都是比较的内存地址,但是java提供的类中,大多都重写了equals(),使equals()比较的是两者对象的值。

                                图1

下面为了验证equals方法有被重写,我重写了equals()方法

输出结果:

由此也就真相大白了。

那么equals和hashCode有何关系?

想知道两者之间的关系,我们先了解一下hashCode是什么,这里我从网上找了更权威的相关解释

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。

从源码可以看到,hashCode源自Object类中,也就是java中所有类都有hashCode方法。 虽然,每个Java类都包含hashCode() 函数。但是,仅仅当创建并某个“类的散列表”(关于“散列表”见下面说明)时,该类的hashCode() 才有用(作用是:确定该类的每一个对象在散列表中的位置;其它情况下(例如,创建类的单个对象,或者创建类的对象数组等等),类的hashCode() 没有作用。
       上面的散列表,指的是:Java集合中本质是散列表的类,如HashMap,Hashtable,HashSet。

 

       也就是说:hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

那么散列码是什么?

不必用冗长的线性搜索技术来查找一个键,而是用一个特殊的值,名为“散列码”。散列码可以获取对象中的信息,然后将其转换成那个对象“相对唯一”的整数(int)。所有对象都有一个散列码,而hashCode()是根类Object的一个方法...

  实际的使用中,一个对象一般有key和value,可以根据key来计算它的hashCode。假设现在全部的对象都已经根据自己的hashCode值存储在不同的存储区域中了,那么现在查找某个对象(根据对象的key来查找),不需要遍历整个集合了,现在只需要计算要查找对象的key的hashCode,然后找到该hashCode对应的存储区域,在该存储区域中来查找就可以了,这样效率也就提升了很多。说了这么多相信你对hashCode的作用有了一定的了解,下面就来看看hashCode和equals的区别和联系。

Java对于eqauls方法和hashCode方法是这样规定的:
1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法,也就是说hashCode值要和类中的成员变量挂上钩,对象相同–>成员变量相同—->hashCode值一定相同。
2 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。

对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

这种大量的并且快速的对象对比一般使用的hash容器中,比如hashset,hashmap,hashtable等等,比如hashset里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了。

 

        Person p1 = new Person(18);
        Person p2 = new Person(18);
        System.out.println(p1.equals(p2));//true

p1.equals(p2)返回true,是因为equals()被重写,而hashcode()没有被重写,p1.hashCode()==865113938,p2.hashCode()==1442407170,因此两者的hashCode不相同,违背了hibernate的原则 由此hibernate会产生错误判断,又以为它们不是同一个对象,因此我们还得重写hashCode方法。如何重写hashCode方法呢?

哈希码(HashCode)

哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。

哈希码要完成这么一件事,首先要保证如果equlas出来的结果相等,那么hashCode也相等。像上面的u1和u2,由于名字都是“张三”,所以应该返回相同的hashCode。所以我们可以想一个办法。让Person的哈希码返回Person里面age字段的哈希码,这样就保证,年龄相同的人,不但equlas方法相同,而且hashCode相等。

重写之后:

class Person{
	private String age;

	public Person(String age) {
		this.age = age;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}


	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof Person)) {
			return false;
		}
		Person p = (Person) obj;
		if(this.age==p.age) {
			return true;
		}else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		return age.hashCode();
	}
	

这样可以保证hibernate根据我们自己的需求来判断重复对象。

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

                Person p1 = new Person("17");
		Person p2 = new Person("18");
		System.out.println(p1.equals(p2));
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());

结果:

false
1574
1575

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值