Java 编译器或JVM是否强制执行hashCode/equals契约?
我在HashMap中存储的对象作为键覆盖equals(),而不是hashCode();当我在映射中放置对象时,没有调用equals()方法。如果我还重写hashCode(),则会调用equals()方法。为什么呢 为什么我不能使用自定义equals方法来阻止向映射添加对象,而不管我是否重写hashCode() 谢谢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)
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()