为什么在添加HashSet和hashCode匹配时没有调用equals()? [英] Why is equals() not called while adding to HashSet and hashCode matches?

查看:91
本文介绍了为什么在添加HashSet和hashCode匹配时没有调用equals()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行此代码时,为什么只有 hashCode()被调用而不是等于方法,而我的 hashCode()实现为 HashSet 的两个条目生成相同的 hashCode

When I run this code why only hashCode() is called not equals method while my hashCode() implementation generate same hashCode for both entries to HashSet?

import java.util.HashSet;

public class Test1 {
    public static void main(String[] args) {
        Student st=new Student(89);
        HashSet st1=new HashSet();
        st1.add(st);
        st1.add(st);
        System.out.println("Ho size="+st1.size());
    }
}
class Student{
    private int name;
    private int ID;
    public Student(int iD) {
        super();
        this.ID = iD;
    }
    @Override
    public int hashCode() {
        System.out.println("Hello-hashcode");
        return ID;
    }
    @Override
    public boolean equals(Object obj) {
        System.out.println("Hello-equals");
        if(obj instanceof Student){
            if(this.ID==((Student)obj).ID){
                return true;
            }
            else{
                return false;
            }
        }
        return false;  
    }
}

此输出为:

Hello-hashcode
Hello-hashcode
Ho size=1


推荐答案

哈希集首先检查引用相等性,如果超过,则跳过 .equals 致电。这是一个优化并且有效,因为的合约等于指定如果 a == b 那么 a.equals(b)中

The hash set checks reference equality first, and if that passes, it skips the .equals call. This is an optimization and works because the contract of equals specifies that if a == b then a.equals(b).

我附上了下面的源代码,突出显示了这个检查。

I attached the source code below, with this check highlighted.

如果你改为添加两个相等的元素不是相同的参考,你得到你期望的效果:

If you instead add two equal elements that are not the same reference, you get the effect you were expecting:

    HashSet st1=new HashSet();
    st1.add(new Student(89));
    st1.add(new Student(89));
    System.out.println("Ho size="+st1.size());

结果

$ java Test1
Hello-hashcode
Hello-hashcode
Hello-equals
Ho size=1






这是来自OpenJDK 7的源代码,指示了相等优化(来自HashMap,HashSet的底层实现):


Here's the source code from OpenJDK 7, with equality optimization indicated (from HashMap, the underlying implementation of HashSet):

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
//                                         v-- HERE
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

这篇关于为什么在添加HashSet和hashCode匹配时没有调用equals()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆