揭开HashCode()和equals()的面纱

在JAVA中,我们通常知道

  • 如果两个对象相同(equal()返回true),那么他们的hashcode值一定相同。
  • 如果两个对象不同(equal()返回false),他们的hashcode值也可能相同
    为什么会出现这样的情况,hashCode()和equals()到底有什么不同。下面就让我们来详细了解他们

HashCode的定义

HashCode也称为哈希值或者散列值。在JAVA中,hashCode值由hashCode()方法返回。hashCode()方法在Object类中,因此所有的对象都可以通过hashCode()方法求出其对应的哈希值。下面给出Object类中的hashCode()方法

    public int hashCode() {
        int lockWord = shadow$_monitor_;
        final int lockWordMask = 0xC0000000;  // Top 2 bits.
        final int lockWordStateHash = 0x80000000;  // Top 2 bits are value 2 (kStateHash).
        if ((lockWord & lockWordMask) == lockWordStateHash) {
            return lockWord & ~lockWordMask;
        }
        return System.identityHashCode(this);
    }

identityHashCode()方法是System类中的静态方法,根据对象内存地址来计算哈希值。
hashCode()方法可以被override,例如String类中的hashcode()

    @Override 
    public int hashCode() {
        int hash = hashCode;
        if (hash == 0) {
            if (count == 0) {
                return 0;
            }
            final int end = count + offset;
            final char[] chars = value;
            for (int i = offset; i < end; ++i) {
                hash = 31*hash + chars[i];
            }
            hashCode = hash;
        }
        return hash;
    }

重点在里面的那个for循环,JDK1.7u4文档上解释为
s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1] 这种算法。通过这样来求得哈希值。
上面是String类中的hashcode()方法,我们还有Double ,float ,AbstractList等类都重写了这个方法来获取哈希值。

哈希值的用处

到这里为止我们知道了哈希值的定义。那么我们为什么需要用到hashCode()这个方法呢?
效率!效率!效率!重要的事情说三遍。举个例子,当我们在Set数据结构中插入新的数据时,首先需要查重,那么判别在集合中是否已经存在该数据对象了就显得至关重要了。我们可以用equals()方法来从头到尾遍历,但是显得效率不高。如果我把集合分成若干个小组,我知道这个待插入数据在哪个小组里面,直接去那个小组查找,这样就显得高效多了。哈希值就好比这个小组序号。找到小组后再根据equals()方法来逐个查找是否含有重复的对象。
当两个不同对象产生了相同的哈希值时,我们管这种现象叫做碰撞。可以这样来考虑,我们把某个集合看成一个“链表数组”,哈希值相同表示在同一个数组元素中(也就是在同一个链表中),如果发生了碰撞,那么新的对象将会被添加到链表的末端。
以上就是为什么hashcode的用途浅析了,而HashSet,HashMap,HashTable就是它的典型应用。

equals()方法注意事项

假设x,y,z为非空对象

  • 对称 x.equals(y)和y.equals(x)对象的返回值相同
  • 反射 x.equals(x)返回true.
  • x.equals(null)返回false.
  • x.equals(不同类型的对象y)返回false
  • 类推性 如果x.equals(y),y.equals(z),那么z.equals(x)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值