1、==
==是运算符,用于比较两个变量是否相等,而equals是Object类的方法,用于比较两个对象是否相等。默认Object类的equals方法是比较两个对象的地址,此时和==的结果一样。换句话说:基本类型比较用==,比较的是他们的值。默认下,对象用==比较时,比较的是内存地址,如果需要比较对象内容,需要重写equal方法。
2、equals
1、默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。下面是Object类中equals方法:
public boolean equals(Object obj) { |
定义的equals与==是等效的
2 、要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。下面是String类对equals进行了重写:
这里对equals重新需要注意五点:
1 自反性:对任意引用值X,x.equals(x)的返回值一定为true.
2 对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
3 传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true
4 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变
5 非空性:任何非空的引用值X,x.equals(null)的返回值一定为false
|
这样就重写了一个考虑得比较全面的equals方法,但是我们知道重写equals方法还需要重写hashCode方法,这是为什么呢?
首先我们需要知道hashCode的作用,java中的hashCode的作用主要是用增加哈希存储结构(HashMap HashTable之流)的查找速度,这些哈希存储结构可以通过hashCode来确定对象在哈希存储结构中的存储位置。通过这么一个作用的描述,我们应该get到以下几点:
1、hashCode作用主要在于增加数据在哈希家族中的查询速度。
2、如果hashCode相等,他们在哈希结构中存储位置相等,但是不是同一个对象!换句话说hashCode相等,调用equals不一定相等。
3、如果equals相等,那么他们的存储位置当然相等,所以hashCode一定也是相等的。
4、根据2、3两条,重写equals方法就一定要重写hashCode方法。
public class Main { |
在java的哈希系列存储结构中,get(Object obj)方法首先会根据obj.hashCode()找到obj这个对象在这个哈希存储结构中的存储位置,然后比较obj和这个存储位置上的元素是否相等,这样就增加了效率,如果hashCode不一样,说明这个key值和obj不对应(毕竟存储位置都不一样,对象当然不一样);如果hashCode一样,然后才调用equals方法,判断这个位置存储的哪个元素是自己要寻找的,或者这个位置存储的所有元素都不是要找的obj。所以当我们没有重写hashCode方法的时候,虽然get(Object obj)中的obj和需要判断的key对象是相等的,但是hashCode不一样,于是便不能找到obj这个key的位置,当然也就找不到对应的value。
重写hashcode()
|
3、hashCode的作用
想要明白,必须要先知道Java中的集合。总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。
如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;
如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
4、equals()和hashcode()的联系
hashCode()是Object类的一个方法,返回一个哈希值。如果两个对象根据equal()方法比较相等,那么调用这两个对象中任意一个对象的hashCode()方法必须产生相同的哈希值。
如果两个对象根据eqaul()方法比较不相等,那么产生的哈希值不一定相等(碰撞的情况下还是会相等的。)
Java对于eqauls方法和hashCode方法是这样规定的:
(1)同一对象上多次调用hashCode()方法,总是返回相同的整型值。
(2)如果a.equals(b),则一定有a.hashCode() 一定等于 b.hashCode()。
(3)如果!a.equals(b),则a.hashCode() 不一定等于 b.hashCode()。此时如果a.hashCode() 总是不等于 b.hashCode(),会提高hashtables的性能。
(4)a.hashCode()==b.hashCode() 则 a.equals(b)可真可假
(5)a.hashCode()!= b.hashCode() 则 a.equals(b)为假。