[英]How hashcode stores values
我上课了
public class Customer {
private int customerId;
private String customerName;
private String customerType;
private String customerAddress;
public Customer(int customerId, String customerName, String customerType, String customerAddress) {
super();
this.customerId = customerId;
this.customerName = customerName;
this.customerType = customerType;
this.customerAddress = customerAddress;
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerType() {
return customerType;
}
public void setCustomerType(String customerType) {
this.customerType = customerType;
}
public String getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}
@Override
public String toString() {
return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerType="
+ customerType + ", customerAddress=" + customerAddress + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((customerAddress == null) ? 0 : customerAddress.hashCode());
result = prime * result + ((customerName == null) ? 0 : customerName.hashCode());
result = prime * result + ((customerType == null) ? 0 : customerType.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (customerAddress == null) {
if (other.customerAddress != null)
return false;
} else if (!customerAddress.equals(other.customerAddress))
return false;
if (customerName == null) {
if (other.customerName != null)
return false;
} else if (!customerName.equals(other.customerName))
return false;
if (customerType == null) {
if (other.customerType != null)
return false;
} else if (!customerType.equals(other.customerType))
return false;
return true;
}
}
请注意,我已从等于和哈希码计算中删除了customerId。 我创建此方法以使用客户对象作为键
public static Map<Customer, String> testKeysWithObject(){
Map<Customer, String> map = new HashMap<>();
Customer customer1 = new Customer(1, "customerName1", "customerType1", "customerAddress1");
Customer customer2 = new Customer(2, "customerName2", "customerType2", "customerAddress2");
Customer customer3 = new Customer(3, "customerName3", "customerType3", "customerAddress3");
Customer customer4 = new Customer(4, "customerName4", "customerType4", "customerAddress4");
map.put(customer1, "customer1");
map.put(customer2, "customer2");
map.put(customer3, "customer3");
map.put(customer4, "customer4");
customer4 = new Customer(5, "customerName5", "customerType5", "customerAddress5");
customer3.setCustomerAddress("customerAddress5");
System.out.println(customer4.getCustomerAddress());
return map;
}
以下方法遍历Hashmap。
public static void displayMap(Map<Customer, String> map) {
System.out.println("================================== ENTRY SET ==========================================");
for (Entry<Customer, String> mapKeys : map.entrySet()) {
if(null != mapKeys)
System.out.println("Key -> " + mapKeys.getKey() + " Value -> " + mapKeys.getValue()+ " HashCode -> " + mapKeys.hashCode());
}
System.out.println();
System.out.println("================================== KEY SET ==========================================");
for (Customer mapKeys : map.keySet()) {
if(null != map.get(mapKeys))
System.out.println("Key -> " + mapKeys + " Value -> " + map.get(mapKeys) + " HashCode -> " + map.get(mapKeys).hashCode());
}
}
以下是输出。
customerAddress5
================================== ENTRY SET ============== ============================密钥 - >客户[customerId = 3,customerName = customerName3,
customerType = customerType3,customerAddress = customerAddress5]值 - > customer3 HashCode - > 291012570密钥 - >客户[customerId = 4,customerName = customerName4,customerType = customerType4,customerAddress = customerAddress4]值 - > customer4 HashCode - > 291011640密钥 - >客户[ customerId = 2,customerName = customerName2,customerType = customerType2,customerAddress = customerAddress2] Value - > customer2 HashCode - > 291210360 Key - > Customer [customerId = 1,customerName = customerName1,customerType = customerType1,customerAddress = customerAddress1] Value - > customer1 HashCode - > 291211416================================== KEY SET ============== ============================密钥 - >客户[customerId = 4,customerName = customerName4,
customerType = customerType4,customerAddress = customerAddress4] Value - > customer4 HashCode - > 1611562006 Key - > Customer [customerId = 2,customerName = customerName2,customerType = customerType2,customerAddress = customerAddress2] Value - > customer2 HashCode - > 1611562004 Key - > Customer [ customerId = 1,customerName = customerName1,customerType = customerType1,customerAddress = customerAddress1] Value - > customer1 HashCode - > 1611562003
我对这个hashmap行为有几个问题
为什么hashmap不受customer4 = new assignment的影响,hashcode如何存储这些。
您正在为customer4
变量分配新对象,您不会更改对象本身。 Map保存对旧对象的引用,并且不知道您已更改customer4
。
hashMap如何影响customer3.setCustomerAddress(“customerAddress5”);
您正在更改对象本身。 地图中的customer3
和customer都指向同一个对象。
为什么keyset()和entryset方法返回了两个不同的值。
永远不要将可变对象作为键。 或者至少在放入地图后不要改变它们。 地图无法处理此更改,无法重新排序条目。 这就是"customerAddres5"
的密钥被“遗漏”的原因。
我可以看到更改反映在entryset()而不是keyset()中,这让我想知道hashmap如何能够用一种方法而不是另一种方法来应对更改。
entrySet
方法返回带有(key - > value)对的整个集合。 你检查null != mapKeys
在这里是多余的,因为它们都不是空的并且它们已经相互连接。
keySet
方法仅返回键。 它还返回4个项目,但您要过滤掉带有"customerAddress5"
条目,因为您试图通过此键获取值。 但是,由于您更改了address
字段并且映射无法检索此键的值,因此该密钥的哈希码已更改。
结论: 永远不要改变关键状态。 让它变得一成不变,所以没人能改变它。
hashmap是否存储实际对象的引用,如果引用则为什么customer4 = new对hashmap没有影响?
您正在重新分配customer4
。 再次阅读第一个问题的答案。
您必须了解的是,您的四个Customer
变量中的每一个都只是对某个Object的引用。 当你调用map.put(customer4, "customer4");
,你要说'使用变量customer4
引用的对象作为值“customer4”'的键。 当您使用new
语句重新分配customer4
时,不会修改Object,而是更改customer4
,以便它不再引用该第一个Object。
至于你的第二个问题, customer3
同样是对变量的引用。 在指定customer3
以引用new
Object之后,将该Object放入HashMap
。 现在有两个对这个对象的引用; 其中一个是customer3
,另一个是HashMap
的条目。 当您调用setCustomerAddress()
,您现在正在对该Object进行操作,因此从这两个参考点可以看到更改。
至于为什么keyset()和entryset()方法返回不同的hashCode
,在你的第一个循环中, mapKeys
是Entry
类型,而在第二个循环中, map.get(mapKeys)
是String
类型,所以它们自然会产生不同的hashCode
。
最后,Java中的所有内容都是参考。 当您put
customer4放入Map时,您实际上是在引用Object。 当您重新分配customer4时,您只是将变量指向另一个Object,但该引用的另一个副本并没有消失。 因此,更改变量customer4
不会影响Map中的条目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.