什么是hashmap碰撞?它出现在我的代码中吗?

时间:2017-06-15 10:45:10

标签: java hashmap

我编写了一个代码,其中包含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只保存单个键值对。

所以我的问题是碰撞发生在哪里?

密钥可以指向多个值吗?

在搜索相应密钥的值时,链接列表概念出现在哪里?

有人可以就我分享的例子解释上述事项吗?

1 个答案:

答案 0 :(得分:1)

  

什么是hashmap碰撞?

没有“hashmap collision”这样的东西。

存在“哈希码冲突”之类的问题。当两个对象具有相同的哈希码但不相等时会发生这种情况。

Hashcode冲突不是问题......除非频繁发生。正确设计的哈希表数据结构(包括HashMapHashSet)将应对冲突,但如果冲突概率过高,性能将会受到影响。

  

我的代码中是否出现[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 = .....