Java 编译器或JVM是否强制执行hashCode/equals契约?

Java 编译器或JVM是否强制执行hashCode/equals契约?,java,equals,hashcode,Java,Equals,Hashcode,我在HashMap中存储的对象作为键覆盖equals(),而不是hashCode();当我在映射中放置对象时,没有调用equals()方法。如果我还重写hashCode(),则会调用equals()方法。为什么呢 为什么我不能使用自定义equals方法来阻止向映射添加对象,而不管我是否重写hashCode() 谢谢 package package1; public class PlayWithHash { public static void main(String [] args)

我在HashMap中存储的对象作为键覆盖equals(),而不是hashCode();当我在映射中放置对象时,没有调用equals()方法。如果我还重写hashCode(),则会调用equals()方法。为什么呢

为什么我不能使用自定义equals方法来阻止向映射添加对象,而不管我是否重写hashCode()

谢谢

package package1;

public class PlayWithHash {

    public static void main(String [] args){
        java.util.Map<Cat, Cat> map = new java.util.HashMap<Cat, Cat>();
        map.put(new Cat(), new Cat());
        map.put(new Cat(), new Cat());
        System.out.println("hashmap size = " + map.size());
    }
}

class Cat{
    @Override
    public int hashCode(){
        return 1;
    }
    @Override
    public boolean equals(Object d){
        Cat c = (Cat) d;
        if(this.hashCode() == c.hashCode()){
            return true;
        }
        return false;
    }
}
package1;
公共类PlayWithHash{
公共静态void main(字符串[]args){
java.util.Map Map=new java.util.HashMap();
map.put(new Cat(),new Cat());
map.put(new Cat(),new Cat());
System.out.println(“hashmap size=“+map.size());
}
}
班猫{
@凌驾
公共int hashCode(){
返回1;
}
@凌驾
公共布尔等于(对象d){
c类=d类;
if(this.hashCode()==c.hashCode()){
返回true;
}
返回false;
}
}
如果注释了hashCode(),则大小为2,否则大小为1

我在想,如果我不重写hashCode(),而是使用对象的hashCode(),HashMap将“看到”我的两个对象的hashCodes是不同的,并得出结论,没有必要调用equals()。如果这是真的,HashMap至少是合同的一部分。而且,这可能是HashMap优化的另一种表现形式

但是,您(greenSocksRock)写道,“……密钥的hashCode()实现没有为不同的密钥返回足够不同的哈希值。”请详细说明一下

谢谢

package package1;

public class PlayWithHash {

    public static void main(String [] args){
        java.util.Map<Cat, Cat> map = new java.util.HashMap<Cat, Cat>();
        map.put(new Cat(), new Cat());
        map.put(new Cat(), new Cat());
        System.out.println("hashmap size = " + map.size());
    }
}

class Cat{
    @Override
    public int hashCode(){
        return 1;
    }
    @Override
    public boolean equals(Object d){
        Cat c = (Cat) d;
        if(this.hashCode() == c.hashCode()){
            return true;
        }
        return false;
    }
}

PS很抱歉,我仍在试图找到解决StackOverflow编辑器问题的方法。

恐怕编译器没有强制执行它。 为了更好地理解这个主题,请阅读此文
如果编译器没有强制执行它。 为了更好地理解这个主题,请阅读此文
如果编译器没有强制执行它。 为了更好地理解这个主题,请阅读此文
如果编译器没有强制执行它。 为了更好地理解这个主题,请阅读此文
编译器和JVM都不强制执行hashCode/equals契约。 合同在
对象
您的类之间,即您有责任遵守和执行该合同

在Java中,
对象
类为大多数基于哈希的标准库类所依赖的
.equals()
.hashCode()
制定了契约。现在,如果您实现自己的类,它会隐式地扩展
对象
,因此,如果您希望您的类与依赖该约定的其他类正确工作,您应该在自己的实现中强制执行通用约定

作为提醒,请参阅:

如果根据equals(Object)方法两个对象相等,那么对两个对象中的每一个调用hashCode方法必须产生相同的整数结果

在没有看到您的实现的情况下,我只能猜测,当您将对象放入
映射中时,为什么会调用
equals()
,我的猜测是,您的键的
hashCode()
实现没有为不同的键返回足够不同的哈希值。
例如,当您将某些内容放入
HashMap
时,它将调用键的
hashCode()
方法,以找到一个位置来存储您的值。如果该点已经包含一个值,则可能会调用键的
equals()
方法来确定下一步要做什么

我不确定我是否理解你在上一个问题中试图做什么,当你说你想“阻止向地图添加对象”时。如果您愿意的话,使用自定义的
equals
实现肯定可以做到这一点。在将新条目放入映射之前,根据您的情况查看
Map.containsKey()
Map.containsValue()


最后,如果可以的话,我建议查看Joshua Bloch中的第8项和第9项,以获得更深入的解释。

编译器和JVM都不强制执行hashCode/equals契约。 合同在
对象
您的类之间,即您有责任遵守和执行该合同

在Java中,
对象
类为大多数基于哈希的标准库类所依赖的
.equals()
.hashCode()
制定了契约。现在,如果您实现自己的类,它会隐式地扩展
对象
,因此,如果您希望您的类与依赖该约定的其他类正确工作,您应该在自己的实现中强制执行通用约定

作为提醒,请参阅:

如果根据equals(Object)方法两个对象相等,那么对两个对象中的每一个调用hashCode方法必须产生相同的整数结果

在没有看到您的实现的情况下,我只能猜测,当您将对象放入
映射中时,为什么会调用
equals()
,我的猜测是,您的键的
hashCode()
实现没有为不同的键返回足够不同的哈希值。
例如,当您将某些内容放入
HashMap
时,它将调用键的
hashCode()
方法,以找到一个位置来存储您的值。如果该点已经包含一个值,则可能会调用键的
equals()
方法来确定下一步要做什么

我不确定我是否理解你在上一个问题中试图做什么,当你说你想“阻止向地图添加对象”时。如果您愿意的话,使用自定义的
equals
实现肯定可以做到这一点。查看
Map.containsKey()
Map.containsValue()