我无法理解以下代码中发生的事情。
我所做的是,我有一个外部课程Employee
包含一些字段:id,
panNo ,
名称and
地址. Then I have an inner class(it was not actually necessary to have it as an inner class) with
id {{1 } panNo`字段及其值与其外部类成员相同。
根据我对and
的了解,我们使用它们来存储键值对。
密钥具有HashMaps
值,并且根据此hashcode
值对值进行哈希处理。当我们在键的帮助下检索值时,再次评估其hashcode
值,然后获取适当的值。
所以,hashcode
必须是这样的:
键----->它的哈希码|参考字段-------->引用值对象。
因此,当我尝试插入具有相同键的对象时,插入最后一个的元素仅可用。这是因为,必须有唯一键,这意味着hashmap
值应该只引用一个对象。
现在,我在代码中所做的是,我在地图中插入hashcode
对象并使用Employee
类作为返回相同EmployeeKey
值的键,即1每次。所以根据我的理解,地图中应该只有一个元素。但这种情况并没有发生.....我不理解某些事情。
我写过以下课程:
hashcode
并且有一个测试类如下:
package package1;
public class Employee {
int id;
int panNo;
String name;
String address;
public Employee(int id, int panNo, String name, String address) {
this.id = id;
this.panNo = panNo;
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "Employee [id=" + id + ", panNo=" + panNo + ", name=" + name + ", address=" + address + "]";
}
public class EmployeeKey {
int id = Employee.this.id;
int panNo = Employee.this.panNo;
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EmployeeKey other = (EmployeeKey) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (id != other.id)
return false;
if (panNo != other.panNo)
return false;
return true;
}
private Employee getOuterType() {
return Employee.this;
}
}
}
答案 0 :(得分:1)
以下是HashMap
中密钥查找的各个阶段。
hash
key.hashCode()
equals
检查该存储桶中的每个密钥来搜索该存储桶中的密钥。您已经hashCode
返回1
,所以您的所有商品都会放在同一个存储桶中,但equals
仍然会为这两个键返回false
。< / p>
Employee e1 = new Employee(1, 123, "neeraj", "pune");
Employee e2 = new Employee(2, 456, "viraaj", "pune");
System.out.println(e1.new EmployeeKey().id);
Map<Employee.EmployeeKey, Employee> myMap = new HashMap<Employee.EmployeeKey, Employee>();
Employee.EmployeeKey k1 = e1.new EmployeeKey();
myMap.put(k1, e1);
Employee.EmployeeKey k2 = e2.new EmployeeKey();
myMap.put(k2, e2);
System.out.println("Size:" + myMap.size());
System.out.println("Hashcode of inner class e1: "
+ e1.new EmployeeKey().hashCode());
System.out.println("Hashcode of inner class e2: "
+ e2.new EmployeeKey().hashCode());
System.out.println("Equals of keys: "
+ k1.equals(k2));
System.out.println(myMap.get(e1.new EmployeeKey()));
答案 1 :(得分:1)
不,哈希表使用哈希码来决定哪个&#34;哈希桶&#34;用于钥匙。但哈希码不一定是唯一的。总是存在碰撞的可能性,这实际上经常发生。
因此,正确的哈希表仅使用哈希码作为决定元素存储位置的第一步,但它必须具有某种冲突解决方案 - 一种使用相同哈希码存储不同键的方法。这通常意味着在哈希表的每个元素中都有一个链表或一个实际键树。
当您将密钥放入哈希表时,它首先计算哈希码以进行第一个决策。但随后它使用equals()
方法来确定它是否与该位置的现有密钥相同的密钥。如果是,则新条目将替换旧条目,并且密钥将保持唯一。但如果它不是相同的密钥 - equals()
返回false
- 那么尽管具有相同的哈希码,新密钥将被单独保存(添加到链表或树)。 / p>
当你想通过密钥检索一个值时,它会再次计算哈希码,但是然后使用equals()
方法将密钥与该位置的所有密钥进行比较在表中(链表或树)。如果密钥等于存储的密钥,它将仅返回该值。如果没有相等的密钥,那么虽然哈希码是相同的,但密钥不被认为是相同的。
这就是为什么同时覆盖hashCode()
和equals()
方法始终很重要,并确保它们是根据对象中的相同字段计算的。
为所有对象返回相同的哈希代码不会违反哈希表的唯一性,但它会降低其性能,因为有效地,而不是基于哈希表的哈希表计算hashCode()
和有限数量的equals()
调用时,哈希表中有一个有效单元格,并且您的数据结构已成为链接列表或树 - 使用线性搜索。