为什么 HashMap get() 方法 returns 在修改插入的对象后为 null?
Why does HashMap get() method returns null after modifying an inserted object?
我实现了 overriding equals and hashCode correctly。在下面的代码中,当我打印出 map 和 num1 时,我可以在控制台中看到它们都有更新的 hashCode()。但是当我试图将它从地图中取出时,它说它是空的。谁能帮忙解释一下为什么 .get() 方法找不到它?
class Phone {
int number;
Phone(int number) {this.number = number;}
public int hashCode() {
return number;
}
public boolean equals(Object o) {
if (o != null && o instanceof Phone)
return (number == ((Phone)o).number);
else
return false;
}
public static void main(String args[]) {
Map<Phone, String> map = new HashMap<>();
Phone num1 = new Phone(2500);
map.put(num1, "John");
num1.number = 100;
System.out.println(map);
System.out.println(num1);
System.out.println(map.get(num1)); // why does it print null
}
}
它returnsnull,因为你改变了num1对象的个数,从而改变了它的hashcode。哈希映射使用 hashcode() 来存储和检索对象,因此当您更改它时,您会在错误的位置查找对象,因为它存储在编号为 2500 的位置,但随后您会在位置 100 查找它。那是因为您的hashcode returns 数字。希望这有帮助。
您创建了一个问题,因为您在将密钥放入 Map 后修改了密钥,该 Map 根据数字从您的 hashcode 方法中进行了哈希处理。
稍微清理一下您的代码。更具体地说,使数字不可变,并且只能通过 public getter 方法访问数字。您不应允许 Map 中的键可变。
public class MyNumber {
private int number;
public MyNumber(int number) {
this.number = number;
}
public int getNumber(){
return number;
}
@Override
public int hashCode() {
return number;
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof MyNumber) {
return (number == ((MyNumber) o).number);
}
else {
return false;
}
}
@Override
public String toString(){
return this.getClass().getName() + "(" + number + ")";
}
}
我已经在您的主要代码中添加了注释 class:
import java.util.HashMap;
import java.util.Map;
public class OverrideHashCode {
public void mutableObjectKeys() {
Map<MyNumber, String> map = new HashMap<>();
MyNumber num1 = new MyNumber(2500);
map.put(num1, "Shreya");
System.out.println(map);
System.out.println(num1);
//This line was your issue. You placed the MyNyumber in the map
//The hashcode pulls the number value from MyNumber to hash the entry (2500 )
//Then you change the value of number
//num1.getNumber() = 100;
System.out.println(map);
System.out.println(num1);
//This was hashed at 2500, but you changed the MyNumber to 100 - no match
System.out.println(map.get(num1)); // prints null - not anymore
//Let's put a second object in the Map
map.put(new MyNumber(500), "GroovyIsBetter!");
//When you work with Maps, you are commonly trying to get values out of the map based on the key.
//In this example, our key's are MyNumber(s)
//We have made MyNumber.number immutable (which is good).
//Because you implemented your own hashcode and equals, you can even pull the value out of the map
//with a new MyNumber object that has the same number value as the original key you placed in the map
System.out.println("\n" + map.get(new MyNumber(2500)));
System.out.println(map.get(new MyNumber(500)));
//Now we can remove one of the keys and recheck
//Should come up null
map.remove(new MyNumber(500));
System.out.println(map.get(new MyNumber(500)));
}
public static void main(String... args){
new OverrideHashCode().mutableObjectKeys();;
}
我实现了 overriding equals and hashCode correctly。在下面的代码中,当我打印出 map 和 num1 时,我可以在控制台中看到它们都有更新的 hashCode()。但是当我试图将它从地图中取出时,它说它是空的。谁能帮忙解释一下为什么 .get() 方法找不到它?
class Phone {
int number;
Phone(int number) {this.number = number;}
public int hashCode() {
return number;
}
public boolean equals(Object o) {
if (o != null && o instanceof Phone)
return (number == ((Phone)o).number);
else
return false;
}
public static void main(String args[]) {
Map<Phone, String> map = new HashMap<>();
Phone num1 = new Phone(2500);
map.put(num1, "John");
num1.number = 100;
System.out.println(map);
System.out.println(num1);
System.out.println(map.get(num1)); // why does it print null
}
}
它returnsnull,因为你改变了num1对象的个数,从而改变了它的hashcode。哈希映射使用 hashcode() 来存储和检索对象,因此当您更改它时,您会在错误的位置查找对象,因为它存储在编号为 2500 的位置,但随后您会在位置 100 查找它。那是因为您的hashcode returns 数字。希望这有帮助。
您创建了一个问题,因为您在将密钥放入 Map 后修改了密钥,该 Map 根据数字从您的 hashcode 方法中进行了哈希处理。
稍微清理一下您的代码。更具体地说,使数字不可变,并且只能通过 public getter 方法访问数字。您不应允许 Map 中的键可变。
public class MyNumber {
private int number;
public MyNumber(int number) {
this.number = number;
}
public int getNumber(){
return number;
}
@Override
public int hashCode() {
return number;
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof MyNumber) {
return (number == ((MyNumber) o).number);
}
else {
return false;
}
}
@Override
public String toString(){
return this.getClass().getName() + "(" + number + ")";
}
}
我已经在您的主要代码中添加了注释 class:
import java.util.HashMap;
import java.util.Map;
public class OverrideHashCode {
public void mutableObjectKeys() {
Map<MyNumber, String> map = new HashMap<>();
MyNumber num1 = new MyNumber(2500);
map.put(num1, "Shreya");
System.out.println(map);
System.out.println(num1);
//This line was your issue. You placed the MyNyumber in the map
//The hashcode pulls the number value from MyNumber to hash the entry (2500 )
//Then you change the value of number
//num1.getNumber() = 100;
System.out.println(map);
System.out.println(num1);
//This was hashed at 2500, but you changed the MyNumber to 100 - no match
System.out.println(map.get(num1)); // prints null - not anymore
//Let's put a second object in the Map
map.put(new MyNumber(500), "GroovyIsBetter!");
//When you work with Maps, you are commonly trying to get values out of the map based on the key.
//In this example, our key's are MyNumber(s)
//We have made MyNumber.number immutable (which is good).
//Because you implemented your own hashcode and equals, you can even pull the value out of the map
//with a new MyNumber object that has the same number value as the original key you placed in the map
System.out.println("\n" + map.get(new MyNumber(2500)));
System.out.println(map.get(new MyNumber(500)));
//Now we can remove one of the keys and recheck
//Should come up null
map.remove(new MyNumber(500));
System.out.println(map.get(new MyNumber(500)));
}
public static void main(String... args){
new OverrideHashCode().mutableObjectKeys();;
}