首先三者都可以用来比较,主要是比较的内容不同
==
:
- 如果是基本类型相比,就是比较他们的值是否相同,因为基本数据类型他们的值是直接存在栈中的
- 如果是引用数据类型比较,就是比较他们的内存地址是否相同,因为对象是存在堆中,而栈中存储的是它的引用内存地址
equals()
:
- 只用于对象之间的比较
- 默认情况下,用的是Object类下的equals()方法,它是用来比较对象的地址值
- 如果在equals()方法被重写的情况下,就要按照重写的方法体去执行比较,比如说String类下的equals就被重写为比较两个对象的内容,(大部分类都重写了equals的方法)
hashCode()
:
- hashcode方法只有在集合中用到
- 返回的是一个数值,目的是生成hash码,hash码的主要用途就是在对对象进行散列的时候作为key输入
- 如果a=b,则h(a) = h(b)
如果a!=b,则h(a)与h(b)可能得到相同的散列值 - 将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。
【 如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等
如果两个对象不equals,他们的hashcode有可能相等
如果两个对象hashcode相等,他们不一定equals
如果两个对象hashcode不相等,他们一定不equals】
- 按照约定一般重写了equals就要重写hashCode
为什么要用hashCode?
想要明白,必须要先知道Java中的集合。
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。
这样一来,当集合要添加新的元素时,
先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。
如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了
如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。