A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 林铁柱 黑马帝   /  2012-2-8 09:17  /  3142 人查看  /  7 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 林铁柱 于 2012-2-8 10:36 编辑

hashCode(),==,equalse()之间的区别,他们都在什么情况下使用比较能提高效率??

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

7 个回复

正序浏览
本帖最后由 最初的理想 于 2012-2-8 16:25 编辑

        ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
        如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
        equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
        String a=new String("foo");
        String b=new String("foo");
        两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。        如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
        boolean equals(Object o){
        return this==o;
        }
        这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
       Java中的集合(Collection)有两类,一类是List,再有一类是 Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次 equals方法。这显然会大大降低效率。    于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。    这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。所以,Java对于eqauls方法和hashCode方法是这样规定的:1、如果两个对象相同,那么它们的hashCode值一定要相同;2、如果两个对象的hashCode相同,它们并不一定相同,上面说的对象相同指的是用eqauls方法比较。
   hashCode()的返回值和equals()的关系如下:
    * 如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
    * 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。


简单点说:hashcode这个方法是用来鉴定2个对象是否相等的。
那你会说,不是还有equals这个方法吗?
不错,这2个方法都是用来判断2个对象是否相等的。但是他们是有区别的。
一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以认为只要姓名和性别相等,那么就说这2个对象是相等的。
hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。
要从物理上判断2个对象是否相等,用==就可以了。

评分

参与人数 1技术分 +2 收起 理由
admin + 2 用心了!

查看全部评分

回复 使用道具 举报
李泽霖 发表于 2012-2-8 09:33
equals()方法,该方法定义在object类中,因此java中的每个类都具有该方法,对于object类中的equals()方法来 ...

重写hashcode方法一般都是在遇到hash集合时候才要这么做,并不是重写了equals方法就一定的重写hashcode方法。
回复 使用道具 举报
张建银 发表于 2012-2-8 10:26
==是比较对象的内存地址和堆中的值,而内存地址在java中用hashcode表示,hashcode代表内存地址
equal一般是 ...

明白了。。
回复 使用道具 举报
==是比较对象的内存地址和堆中的值,而内存地址在java中用hashcode表示,hashcode代表内存地址
equal一般是比较对象的值,要看你怎么去写这个对象的equal方法,也就是说可以自定义比较方法

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
王文龙 发表于 2012-2-8 09:42
我想同学你想问的是在底层为哈希码的集合中hashcode()和equals()方法吧.

hashcode()是用来获取该对象存于 ...

就像我们按照地址找人时,先要看他是哪个省的,再看他是哪个市的。。。这样就比先找和那个相同姓名人要效率的多,是不是这个意思?
回复 使用道具 举报
我想同学你想问的是在底层为哈希码的集合中hashcode()和equals()方法吧.

hashcode()是用来获取该对象存于集合中所分配的哈希值,
若该哈希值位于一定区域内,
会再调用equals方法与这个区域内的所有对象进行比较看是否相等,

若该哈希值位于新的区域,
则不会调用equals方法,
也就是说这两个方法的调用是有先后顺序的.

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
equals()方法,该方法定义在object类中,因此java中的每个类都具有该方法,对于object类中的equals()方法来说,他会判断调用equals()方法的引用于传进来的引用是否一致,即这两个引用是否指向的是同一个对象,对于object的equals方法来说,他等价于==。

String str =new String("AA");

String str2 = new String("AA”):

System.out.pringln(str.equals(str2));

//返回的是true,所以判定string中的equals在string被重写了,所以对于string类的equals()方法来说,他是判断当前字符串与传进来的字符串是否一致,所以相等行判断要用equals方法而不用==


所以面试时候问到==与equals方法的区别,==判断引用一致,而对于object类型来说,equals判断引用对象是不是一样,对于重写了equals方法来说,就是比较内容的相同了,如String类。

关于Object类的equals方法的特点

A) 自反性:x.equals(x)应该返回true

B) 对称性:x.equals(y)为true,那么y.equals(x)也为true。

C) 传递性:x.equals(Y)为true并且y.equals(Z)为true ,那么x.equals(z)也为true

关于Object类的hashcode方法的特点

A) 在java应用的一次执行过程当中对于同一个对象的hashcode方法的多次调用,他们应该返回同样的值

B) 对于两个对象来说如果使用equals方法比较返回true,那么这两个对象的hashcode一定为true

C) 如果两个对象equals方法比较返回false,hashcode可同也可不同

D) 对于object类来说不同的object对象hashcode值是不同的(Object类的hashcode值表示的是对象的地址)

当使用hashset时,hashcode方法就会得到调用,判断已经存储在集合中的对象hashcode值是否与增加的对象hashcode值一致,如不一致,直接加进去,如一致,在进行equals方法的比较,equals方法如果返回true,表示已加进去,就不会在增加新的对象否则加进去。

所以hashset利用hashcode与equals方法作用来内容是否重复,对于string内容相同,hashcode也一样

重写equals方法也要重写hashcode,反之亦然

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马