直到今天我有一个信念,即两个对象具有相同的散列码装置两者具有相同的存储器位置。但是下面的代码总共讲述了一个不同的故事:
学生实体: 公共类学生器具可比{
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输入重复,以检查是否忽略equals&哈希码()如下:
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结果为false。但是为什么呢?
答案 0 :(得分:2)
好吧,hashCode()
总是返回内存地址并不完全正确。在您的特定情况下,您将覆盖该函数以基本上返回Subject
引用的hashCode。
您的评估显示以下输出:
stringops.Student@955a0720
这可能有点令人困惑,因为这实际上不是是裸内存地址,而是对对象的toString()
方法的调用。
Have a look at how Java implements toString
:
getClass().getName() + '@' + Integer.toHexString(hashCode())
因此,实际上,这两个对象具有不同的存储位置,但是由于覆盖了hashCode()
,因此看不到它们。而且,没有办法覆盖Java如何选择对象的内存地址(也许有些黑客除外),但是,两个对象不能具有相同的地址。
下次请添加更多文本而不是屏幕截图,以提高您对其他问题的搜索能力。
答案 1 :(得分:1)
hashcode是由hascode()方法返回的int值。
Object.java定义hascode()和每一Java类是子类Object.java的,因此每个类继承它。
如果特定类的开发者希望重写它,则由他/她决定。一类的开发人员可以选择(虽然一种不好的做法),以用于一个类的所有对象retrun相同恒定int值。
通常,hascode取决于对象的一个或多个属性的值。即使开发人员可能会尽力返回唯一的哈希码,但是(哈希码冲突)两个不同的对象可能最终会返回相同的hascode。
一次只能将一个内存位置分配给一个对象。
两个不同对象(位于内存中两个不同地址)的哈希码可能相同或不同
还有一个相关概念:等号合约和hascode方法。它说如果两个对象通过调用equals返回true,则两个对象必须具有相同的哈希码。请注意,这是定义的合同,但是开发人员可以开发类并编写哈希码方法以遵守合同。错误的实现可能导致两个对象返回不同的hascodes,而equals方法返回true。
答案 2 :(得分:1)
您已经正确地确定了两个不同的对象(即,两个不在同一内存地址的对象)确实可以具有相同的哈希码。的规则是,如果两个对象由.equals()
方法相等,那么它们应产生相同的散列码。除此以外,还有一个普遍的想法,即“不同的对象应尝试使用不同的哈希码”,但不要求位于不同位置的对象应进行不同的哈希处理。
这是一件好事。例如,每个具有相同字符序列的两个不同的String
对象应该直观地具有相同的哈希码,以便HashMap<String, T>
可以正确地查找字符串。这样,提供与用作键的对象不同但具有相同逻辑值的String
对象将可以正常工作;所有String
S采用相同的字符序列的散列到相同的点。