对象的哈希码不是位于堆中的对象的物理内存位置。它将存储在类实例中的数据摘要转换为单个哈希值(32 位有符号整数)。 (来源wiki)
But in case of hashing(HashSet, HashMap etc), we need to override hashcode and equals method
是的,除非您在任何地图实现的类中使用您的类实例作为键。
现在考虑你给定的场景:
@override
int hashcode(){
return id*31;
}
什么都不会发生,但您最终会在地图或场景中添加不同的对象。
重要合同:
对象hashcode和equals方法之间有一个约定,当你覆盖equals时,你必须覆盖hascode(),反之亦然,以便在桶中均匀分布对象。
小心!!
// The worst possible legal hash function - never use!
@Override
public int hashCode() {
return 42;
}
(Source Effective Java)
这是非常合法的,因为它确保相等的对象具有相同的哈希码。这很糟糕,因为它确保每个对象都具有相同的哈希码。因此,每个对象都散列到同一个桶中,散列表退化为链表。应该以线性时间运行的程序改为以二次时间运行。对于大型哈希表,这就是工作和不工作的区别。
为了您的澄清:
考虑到这一点,Bellow 是我的班级,在这里我定义了 equals 和 hascode 之间的约定,表示具有相同滚动和名称的两个对象必须相同。
public class MyClass {
private int roll;
private String name;
private String subject;
public MyClass(int roll, String name, String subject) {
this.roll = roll;
this.name = name;
this.subject = subject;
}
@Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
MyClass myclass = (MyClass) object;
if (this.roll == myclass.getRoll()
&& this.name == myclass.getName()) {
result = true;
}
}
return result;
}
@Override
public int hashCode() {
int hash = 17;
hash = 31 * this.roll;
hash = 31 * hash + this.name.hashCode();
return hash;
}
public static void main(String args[]) {
MyClass obj1 = new MyClass(1, "A", "Math");
MyClass obj2 = new MyClass(1, "A", "Phy");
MyClass obj3 = new MyClass(1, "B", "Chem");
System.out.println("obj1.equals(obj2) : "+obj1.equals(obj2)); // true. As both the objects have the same roll & name
System.out.println("obj1 == obj2 : "+(obj1 == obj2)); // false. because two are references of different instance.
Set<MyClass> set = new HashSet<MyClass>();
set.add(obj1);
set.add(obj2);
System.out.println("set :"+set.size()); // 1 object
for(MyClass cls:set){
System.out.println(cls); //i.e [1 A Math]. It'll not replaced by the 2nd one.
}
Map<MyClass,String> map= new HashMap<MyClass,String>();
map.put(obj1,"IN");
map.put(obj2,"US");
System.out.println("map :"+map.size());// 1 object
for (Map.Entry<MyClass, String> entry : map.entrySet()){
System.out.println(entry.getKey() + " : " + entry.getValue()); // [1 A Math : US]. here you may notice the key remains same but the value will be replaced.
}
}
public int getRoll() {
return roll;
}
public String getName() {
return name;
}
public String getSubject() {
return subject;
}
@Override
public String toString(){
return ""+roll+" "+name+" "+subject;
}
}
注意: 每当您使用new 关键字创建对象时,无论其内容是否相同,每次都会在堆中创建不同的对象。