Java基础拾遗(二) — 关于equals(),hashcode()和 ==

这里分开讲==和equals(),以及equals()和hashcode()的关系

需要先明白对象的内容、对象的引用,基本类型,引用类型这几个概念,此处不做解释

一、==和equals()

1、都是比较"是否相等",但是==是操作符,equals()是所有对象都有的方法

2、==可以用于基本数据类型和引用类型,equals()只能用于引用数据类型

3、对==,当用于基本数据类型时,直接比较变量的值,当用于引用类型时,比较的是对象引用地址

对equals(),如果对象所属的类没有覆盖equals()方法,默认调用的是Object.equals(),比较的也是对象的引用地址是否相同

如果覆盖了equals()方法,那么调用的是对象自己的equals()方法,一般覆盖后比较的是对象内属性值是否都相同

3、Effective Java第8条花了大篇幅讲解覆盖equals需要遵守的通用约定,并给出了证明,这5个约定是:

自反性,对称性,传递性,一致性,以及对任何的非null的x,x.equals(null)必为false

 附,一些常见类覆盖的equals()方法

Object类
    public boolean equals(Object obj) {
        return (this == obj);
    }
String类
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
Integer类
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

二、equals()和hashcode()

Effective Java给出的另一个告诫(实际上编程思想中也有同样的要求):覆盖equals时总要覆盖hashCode

Object规范的第二条:相等的对象必须具有相等的散列码

很明显:equals为true的两个对象的hashcode()方法必须产生相等的整数结果

但是:equals结果为false的两个对象,不一定要产生不同的hashcode结果,意思就是hashcode可以相等

 

三、理解hashCode()

编程思想一书在讲解hashcode时这样描述,"使用散列的目的在于,想要使用一个对象来查找另一个对象;散列的价值在于速度",

设想一下执行HashMap的get(Object key)时,键如果没有按照一定的顺序保存,我们的get操作将变得极其缓慢,散列得以保持键

的排序状态,然后使用Collections.binarySearch()进行查询,注意,这里保存的是键的数字(散列码)而非键本身,前面讲过,不

同的键可能会得到相同的散列码,设计好的散列函数能最大限度保证散列码的不同,特殊情况,散列码仍然有相同的,将使用到

链地址法,有兴趣的可以阅读HashMap的实现源码

posted @ 2018-08-04 16:20  鼠标的博客  阅读(259)  评论(0编辑  收藏  举报