【问题标题】:What is hashmap collisioning ? and does it occurs in my code?什么是 hashmap 冲突?它是否出现在我的代码中?
【发布时间】:2017-06-15 10:45:10
【问题描述】:

我编写了一个代码,其中有学生类和学生对象用作键 如下,

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;
    }

现在当我编译并运行代码时,

方法 example02 中的代码给出的输出为

HASHCODE 372, ID 12, NAME Arnold

即 Set 只包含一个对象,

我的理解是,由于所有对象的键具有相同的哈希码,因此只有一个对象位于存储桶 372 中。我说的对吗?

方法 example03() 也给出输出为

Key : [ HASHCODE 372, ID 12, NAME Arnold ], Value : [ 2 ] 

从上面的方法我们可以看出,由于key返回的hashcode相同, Hashmap 只保存单个键值对。

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

一个键可以指向多个值吗?

在搜索相应键的值时,链表的概念从何而来?

有人可以就我分享的例子向我解释上述内容吗?

【问题讨论】:

  • 哈希冲突不是问题,您的问题是您提供了相同的 ID,并且您只在 equals 方法中检查。

标签: java hashmap


【解决方案1】:

什么是 hashmap 冲突?

没有“hashmap 冲突”之类的东西。

有“哈希码冲突”之类的东西。当两个对象具有相同的哈希码但不相等时,就会发生这种情况。

哈希码冲突不是问题......除非它经常发生。适当设计的哈希表数据结构(包括HashMap 或HashSet)可以应对冲突,但如果冲突概率过高,性能往往会受到影响。


我的代码中是否发生[哈希码冲突]?

没有。

您的代码的问题不是由于哈希码冲突:

  • 您的equals 方法实际上是说两个Student 对象是相等的如果-并且-仅-如果它们具有相同的哈希码。由于您的哈希码仅根据 ID 计算,这意味着具有相同 ID 的任何 Student 对象都是相等的根据定义。

  • 然后添加大量具有相同 ID (12) 和不同名称的 Student 对象。显然,这意味着它们是平等的。这意味着HashSet 在任何给定时间都只会持有其中一个。


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

问题在于Student 对象都相等。

一个键可以指向多个值吗?

这是HashSet 而不是HashMap。没有“钥匙”。 Set 是一组唯一值...其中唯一意味着成员不相等。

在搜索相应键的值时,链表的概念从何而来?

如果您在谈论 LinkedList 类,它不会进入它。

如果你在谈论一般的链表,HashSet 的实现可以使用链表的形式来表示哈希链。但这是一个实现细节,对您的示例没有任何影响。

(如果你真的想知道HashSet是如何工作的,请使用谷歌搜索“java.util.HashSet source”并阅读源代码。注意不同版本的Java实现不同。)


一个键可以指向多个值吗?

没有。 Map API 不支持。

当然你也可以使用这样的地图:

Map<Key, List<Value>> myMultimap = .....

【讨论】:

  • 感谢您的回复。这很有帮助。我的第二个问题是在 hashmap 中一个键是否可以映射到多个值?我关于linkedlist的问题是,在跨hashmap中的每个键获取值时,使用了一个linkedlist数据结构。是真的吗?如果是的话,它是如何工作的,你能解释一下吗?
  • “我关于linkedlist的问题是,在跨hashmap中的每个键获取值时,使用了一个linkedlist数据结构。是真的吗?如果是,它是如何工作的,你能解释一下吗? " - 这两个我都回答了​​。我的答案是阅读源代码 ...因为在 StackOverflow 答案中无法正确解释。
猜你喜欢
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 2019-09-17
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 2011-01-15
相关资源
最近更新 更多