直到今天我有一个信念,即具有相同散列码的两个对象是指两者具有相同的存储空间。但低于一段代码完全讲述了一个不同的故事:
学生实体:公共类学生实现可比{
int id;
int marks;
String Subject;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getMarks() {
return marks;
}
public void setMarks(int marks) {
this.marks = marks;
}
public String getSubjects() {
return Subject;
}
public void setSubject(String subject) {
Subject = subject;
}
public Student() {
}
public Student(int id, String subject, int marks) {
super();
this.id = id;
this.marks = marks;
Subject = subject;
}
@Override
public int compareTo(Student o) {
if (this.getId()>(o.getId()))
return 1;
if (this.getId()<(o.getId()))
return -1;
return 1;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Subject == null) ? 0 : Subject.hashCode());
result = prime * result + id;
result = prime * result + marks;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (Subject == null) {
if (other.Subject != null)
return false;
} else if (!Subject.equals(other.Subject))
return false;
if (id != other.id)
return false;
if (marks != other.marks)
return false;
return true;
}
}
输入重复的HashMap来检查压倒一切是否等于和hashCode()方法的工作原理:
public class TestHashSet3 {
static Student s1;
static Student s2;
static Student s3;
public static void main(String[] args) {
setStudent();
testSet();
testMap();
}
static void testMap() {
Map<Student, String> empMap = new HashMap<>();
empMap.put(s1, "Arun");
empMap.put(s2, "Shivam");
empMap.put(s3, "Varun");
System.out.println("HashMap executed = ");
for (Map.Entry<Student, String> obj : empMap.entrySet()) {
System.out.println(obj + " ");
}
}
static void testSet() {
Set<Student> set = new HashSet<>();
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println("HashSet executed = ");
for (Student student : set) {
System.out.println(student + " ");
}
}
static void setStudent() {
s1 = new Student(124, "Maths", 50);
s2 = new Student(124, "Maths", 50);
s3 = new Student(124, "Maths", 50);
}
}
在过去的截图中我们可以看到,这== OBJ原来是假的。但为什么 ?
嗯,这是不完全真实的hashCode()
总是返回的内存地址。在特定情况下,要覆盖功能基本上返回Subject
参考的哈希码。
你的评价显示以下的输出:
stringops.Student@955a0720
其中,因为这其实不是裸露的内存地址,但你的对象toString()
方法的调用可能会有点混乱。
Have a look at how Java implements toString
:
getClass().getName() + '@' + Integer.toHexString(hashCode())
所以,实际上,这两个对象有不同的存储位置,而是因为你覆盖hashCode()
你不会看到它们。另外,有没有办法覆盖的Java如何选择对象的内存地址(除了一些黑客可能),但尽管如此,两个对象不能有相同的地址。
请提供更多的文字,而不是截图下次来增加你给别人的问题的可搜索性。
你已经正确地只是确定了两个不同的对象 - 即,两个物体不能在同一内存地址 - 的确可以有相同的散列码。的规则是,如果两个对象由.equals()
方法相等,那么它们应产生相同的散列码。除了这一点,一般的想法,“不同的对象应该尽量具有不同的散列码,”没有要求,即在不同的位置的物体应该哈希不同。
这是一件好事,但。例如,两个不同的String
对象均具有相同的字符序列应该直观地具有相同的哈希代码,以便HashMap<String, T>
能够正确查找字符串。通过这种方式,提供了比用作密钥的一个不同的String
对象,但它具有相同的逻辑值,将正常工作;所有String
s用相同的字符序列的散列到同样的地点。
哈希码是通过hascode()方法返回一个int值。
Object.java定义hascode()和每一Java类是子类Object.java的,因此每个类继承它。
这是高达某一类的开发者,如果他/她希望覆盖它。一类开发者可以选择(虽然糟糕的做法),以一类的所有对象retrun相同的恒定int值。
通常hascode是依赖于所述对象的一个或多个属性值。尽管开发者可以尽量让其返回唯一哈希代码,但仍然(哈希码碰撞)两个不同的对象,最终可能eith相同hascode。
在一次一个存储位置只能分配给一个对象。
两个不同的对象(驻留在内存中的两个不同的地址)的哈希码可以是相同的或可以是不同的
另外一个相关概念:平等和hascode方法的合同。它说,如果两个对象具有真正通过调用返回等于则这两个对象必须具有相同的哈希码。请注意,这是定义的合同,但它是高达开发商开发类和写作的hashCode方法坚持合同。一个坏的实施可能导致不同的hascodes由两个对象返回的equals方法返回真。