equals与hashcode

Equals

         Equals是Object类的一个方法,指示某个其他对象是否与此对象“相等”。 Java语言规范要求equals方法具有以下特性:

1、  自反性。对于任何非空引用x,x.equals(x)应该为true

2、 对称性。对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true。

3、 传递性。对于任何引用x、y和z。如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。

4、 一致性。如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)结果不会发生变化。

5、 对于任何非空引用x,x.equals(null)返回false。

Equals与==的区别

         “==” 可以用来判别基础类型或是对象是否相等,但是比较方式存在一些差异。

1、   对于基础类型数据来说,只要他们的值相等,那么就是相等的。

2、   对于对象间的比较来说,比较的就不是他们间的值而是他们的引用,只用引用的对象相等他们才会相等。

         类Object的equals方法,

                       public boolean equals(Object obj){

                return (this == obj);

            }

    此时同“==”没有区别。如果类没有overwrite的话,也同“==”没有任何区别。但是equals可以在子类中overwrite,来重新定义对象相等的条件。就比如String类的equals方法:

    public boolean equals(ObjectanObject) {

        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;

}

对于String类的equals方法来说,引用同一对象或是只要每个位置对应的字符相等,就可以算作是相等。

HashCode

         HashCode(散列码)是由对象导出的一个整数值(可以为负数)。散列码是没有规律的。Hashcode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址(不是真正的内存地址)。当然了,子类也可以overwrite自己的hashcode,可以合理的组合实例域的散列码,以便能够让各个不同的对象产生的散列码更均匀。比如String的散列码就是依据内容导出的。

    public int hashCode() {

        int h = hash;

        if (h == 0 && count > 0) {

            int off = offset;

            char val[] = value;

            int len = count;

 

            for (int i = 0; i < len; i++) {

                h = 31*h + val[off++];

            }

            hash = h;

        }

        return h;

}

Equals与hashcode的定义必须一致。如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。但是hashCode相等的2个对象,equals不一定返回true。例如,如果定义表示员工的类的equals条件是员工ID,那么hashCode方法就需要散列员工ID,而不是员工的名字或是存储地址。

如果存在数组类型的域,那么可以使用静态的Arrays.hashCode方法计算一个散列码,这个散列码有数组元素的散列码组成。

重写hashCode的原则

1、 不必对每个不同的对象都产生一个唯一的hashcode,只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。

2、 生成hashcode的算法尽量使hashcode的值分散一些, 不要很多hashcode都集中在一个范围内,这样有利于提高散列表的性能。

重写Equals方法时需要重写hashCode方法

1、 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数

2、 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。

3、  如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。因为散列表(如:HashMap,HashSet)中,通过hashcode值来判定存储位置(Index),而hashcode相等只能保证两个对象在一个HASH表里的同一条HASH链上,继而通过equals方法才能确定是不是同一对象,如果结果为true, 则认为是同一对象不再插入,否则认为是不同对象继续插入。这样无形中会降低散列表的性能。可见好的hashCode生成算法是可以提高产品性能的。

所以,要满足上述的hashCode特性。且在散列表中存储数据时首先需要通过hashcode来判别存储位置,而相同的对象(equals返回true)不会重复存储,这样如果2个对象equals相同,但是没有重写hashCode方法导致返回的hashcode值不同,可以想象的到,2个对象肯定会保存在散列表的不同位置上的,尽管他们相等。这肯定是不可以的,所以就需要我们重写hashcode方法来保证这种情况不要发生。

当然,如果hashcode生成规则可以产生非常分散的hashcode值,但是在基于需要大量计算的基础上时就需要慎重考虑一下,因为这样做可能会导致一定的效率问题,因为生成hashcode的时间可能远大于查找数据的时间。需要认真的权衡。

另:基本类型不能作为散列表的key使用,是由于基本类型不是继承于Object的,在使用时需要使用它们的封装类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值