2014-08-30 89 views
-2

我想检索HashMap中的另一个元素的值,覆盖equals和hashcode方法。当我为student1和student3使用相同的哈希码并且这两个对象相等时,为什么rollId返回null?理想的情况下,它应该返回我3.下面的代码片段:Map HashCode和Equals

主类

public static void main(String[] args) { 
    Map<Student, Integer> studentMap = new HashMap<Student, Integer>(); 
    Student student1 = new Student(); 
    student1.setRollId(1); 
    Student student2 = new Student(); 
    student2.setRollId(2); 
    studentMap.put(student1, 1); 
    studentMap.put(student2, 2); 
    for (Entry<Student, Integer> entry : studentMap.entrySet()) { 
     if (entry.getValue().equals(1)) { 
      student1.setRollId(3); 
     } 
    } 
    Student student3 = new Student(); 
    student3.setRollId(3); 
    System.out.println("Student1 HashCode " + student1.hashCode() 
      + " Student3 HashCode " + student3.hashCode()); 
    System.out.println("Object Equal === > " + student1.equals(student3)); 
    Integer rollId = studentMap.get(student3); 
    System.out.println("RollId is " + rollId); 

} 


学生班级

private Integer rollId; 

public Integer getRollId() { 
    return rollId; 
} 

public void setRollId(Integer rollId) { 
    this.rollId = rollId; 
} 

@Override 
public int hashCode() { 
    return rollId; 
} 

@Override 
public boolean equals(Object obj) { 
    Student student = (Student)obj; 
    if(this.rollId.equals(student.getRollId())) 
    { 
     return true; 
    } 
    return false; 

} 
+0

你应该张贴整个代码,而不是片段让助手可以测试你的代码。 – 2014-08-30 18:18:34

回答

1

HashMap最终将键值对存储在表中,并且它使用给定键的哈希码来计算表中其索引值。

当修改rollId属性,则也将修改密钥,这反过来会导致在内部表中的查找为一个不同的指数大于所述一个地图的哈希码原本用于存储值。

例如,表格最初可能已经被分配了一定的容量为16,并且两个对条目被存储在索引1和2(给定Student对象中设置的rollId)。将散列键从1更改为3后,映射将搜索 索引3,该索引不存储任何值。

1

不能更改后的哈希键它放在地图上,并期望地图继续正常工作。当您想要更改密钥时,您必须删除该项目,更改密钥并重新插入。

从Java文档:

注意:如果使用可变对象作为map的key很大,一定要小心。如果对象的值以影响等于比较的方式更改,而对象是地图中的关键字,则不会指定地图的行为。

+0

谢谢@Gene。明白了...这是一个可变的物体。 Upvote的答案。 – 2014-08-30 18:25:16

+0

这个答案虽然是一个真实的陈述,但并没有在他的代码中解释问题.. studentMap没有添加任何条目..所以student1 rollId从不改变。查看下面的回答 – ErstwhileIII 2014-08-30 19:02:23

+1

@ErstwhileIII也许他在看完它后改变了他的代码?但是这个'studentMap.put(student1,1); studentMap.put(student2,2);'当我写我的答案时在那里。 – Gene 2014-08-30 21:02:12

0

您的代码存在的问题是您没有为studentMap添加任何值。此外,我不明白你为什么使用整数RollId并从你的hashCode计算int。如果你确实需要Integer来获得更大的范围,那么32位的hashcode(如你所计算的)有可能产生不同的rollIds的副本。考虑更改为int/

试试这个代码:

StudentDriver类

package com.example.student; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 

public class StudentDriver { 
    private static Student student1, student2, student3; 

    public static void main(String[] args) { 
     Map<Student, Integer> studentMap = new HashMap<Student, Integer>(); 

     student1 = new Student(); 
     student2 = new Student(); 

     student1.setRollId(1); 
     student2.setRollId(2); 

     studentMap.put(student1, student1.getRollId()); 
     studentMap.put(student2, student2.getRollId()); 

     for (Entry<Student, Integer> entry : studentMap.entrySet()) { 
      System.out.println("Entry information: " + entry.getValue()); 
      if (entry.getValue().equals(1)) { 

       student1.setRollId(3); 
      } 
     } 

     student3 = new Student(); 
     student3.setRollId(3); 

     System.out.println("Student1 Hashcode = " + student1.hashCode() 
          +", Student3 Hashcode = " + student3.hashCode()) ; 
     System.out.println("Object equal ==> " + student1.equals(student3)); 
     Integer rollId = student3.getRollId(); 
     System.out.println("RollId is " + rollId); 
    } 
} 

Student类

package com.example.student; 

public class Student { 
    // Object fields 
    private Integer rollId; 

    public Integer getRollId() { 
     return rollId; 
    } 
    public Student setRollId(Integer rollId) { 
     this.rollId = rollId; 
     return this; 
    } 

    @Override 
    public int hashCode() { 
     return rollId.intValue(); 
    } 

    @Override 
    public boolean equals(Object other) { 
     return other instanceof Student && ((Student)other).getRollId() == rollId; 
    } 
} 
相关问题