我编写了一个代码,其中包含Student类,学生对象用作键 如下,
public class ExampleMain01 {
private static class Student{
private int studentId;
private String studentName;
Student(int studentId,String studentName){
this.studentId = studentId;
this.studentName = studentName;
}
@Override
public int hashCode(){
return this.studentId * 31;
}
@Override
public boolean equals(Object obj){
boolean flag = false;
Student st = (Student) obj;
if(st.hashCode() == this.hashCode()){
flag = true;
}
return flag;
}
@Override
public String toString(){
StringBuffer strb = new StringBuffer();
strb.append("HASHCODE ").append(this.hashCode())
.append(", ID ").append(this.studentId)
.append(", NAME ").append(this.studentName);
return strb.toString();
}
public int getStudentId() {
return studentId;
}
public String getStudentName() {
return studentName;
}
} // end of class Student
private static void example02() throws Exception{
Set<Student> studentSet = new HashSet<Student>();
studentSet.add(new Student(12, "Arnold"));
studentSet.add(new Student(12, "Sam"));
studentSet.add(new Student(12, "Jupiter"));
studentSet.add(new Student(12, "Kaizam"));
studentSet.add(new Student(12, "Leny"));
for(Student s : studentSet){
System.out.println(s);
}
} // end of method example02
private static void example03() throws Exception{
Map<Student, Integer> map = new HashMap<Student,Integer>();
Student[] students = new Student [] {
new Student(12, "Arnold"),
new Student(12, "Jimmy"),
new Student(12, "Dan"),
new Student(12, "Kim"),
new Student(12, "Ubzil")
};
map.put(students[0], new Integer(23));
map.put(students[1], new Integer(123));
map.put(students[2], new Integer(13));
map.put(students[3], new Integer(25));
map.put(students[4], new Integer(2));
Set<Map.Entry<Student, Integer>> entrySet = map.entrySet();
for(Iterator<Map.Entry<Student, Integer>> itr = entrySet.iterator(); itr.hasNext(); ){
Map.Entry<Student, Integer> entry = itr.next();
StringBuffer strb = new StringBuffer();
strb.append("Key : [ ").append(entry.getKey()).append(" ], Value : [ ").append(entry.getValue()).append(" ] ");
System.out.println(strb.toString());
}
} // end of method example03
public static void main(String[] args) {
try{
example02();
example03();
}catch(Exception e){
e.printStackTrace();
}
}// end of main method
} // end of class ExampleMain01
在Student类的上述代码中,hashcode和equals实现如下,
@Override
public int hashCode(){
return this.studentId * 31;
}
@Override
public boolean equals(Object obj){
boolean flag = false;
Student st = (Student) obj;
if(st.hashCode() == this.hashCode()){
flag = true;
}
return flag;
}
现在,当我编译并运行代码时,
方法示例02中的代码将输出显示为
HASHCODE 372, ID 12, NAME Arnold
即Set只包含一个对象,
我理解为所有对象的键具有相同的哈希码,因此只有单个对象位于桶372中。我是对的吗?
方法example03()也将输出作为
Key : [ HASHCODE 372, ID 12, NAME Arnold ], Value : [ 2 ]
从上面的方法我们可以看到,当键返回相同的哈希码时, Hashmap只保存单个键值对。
所以我的问题是碰撞发生在哪里?
密钥可以指向多个值吗?
在搜索相应密钥的值时,链接列表概念出现在哪里?
有人可以就我分享的例子解释上述事项吗?
答案 0 :(得分:1)
什么是hashmap碰撞?
没有“hashmap collision”这样的东西。
存在“哈希码冲突”之类的问题。当两个对象具有相同的哈希码但不相等时会发生这种情况。
Hashcode冲突不是问题......除非频繁发生。正确设计的哈希表数据结构(包括HashMap
或HashSet
)将应对冲突,但如果冲突概率过高,性能将会受到影响。
我的代码中是否出现[hashcode collision]?
没有
代码问题不是由于哈希码冲突造成的:
您的equals
方法实际上是说两个Student
对象相等 if-and-only-if 它们具有相同的哈希码。由于您的哈希码仅根据ID计算,这意味着具有相同ID的任何Student
对象根据定义等于 。
然后添加许多具有相同ID(12)和不同名称的Student
个对象。显然,这意味着他们是平等的。这意味着HashSet
只会在任何给定时间内持有其中一个。
所以我的问题是碰撞发生在哪里?
问题是Student
个对象都相等。
密钥可以指向多个值吗?
这是HashSet
而不是HashMap
。没有“钥匙”。 Set
是一组唯一值...其中唯一表示成员不相等。
在搜索相应密钥的值时,链接列表概念出现在哪里?
如果你在谈论LinkedList
课程,那么它就不会进入。
如果您正在谈论链接列表,HashSet
的实现可以使用链表的形式来表示哈希链。但这是一个实现细节,而不是对您的示例有任何影响的东西。
(如果你真的想知道HashSet
如何工作,请使用Google搜索“java.util.HashSet source”并阅读源代码。请注意,不同版本的Java中的实现是不同的。)< / p>
密钥可以指向多个值吗?
没有。 Map
API不支持此功能。
但当然你可以使用这样的地图:
Map<Key, List<Value>> myMultimap = .....