首先:HashMap如何工作?
基本上,它具有一个数组,当您在映射中放置键值对时,它存储在数组中的某个位置。根据将键
hashCode()传递给哈希方法的结果来选择数组中的位置。这是为什么?好吧,如果您请求某个键的值,则可以简单地重新计算数组中用于查找键的索引及其关联的值,以再次找到数组中的索引。(需要更多的逻辑来处理映射到相同索引的键,但是我只是想让您了解基本机制)然后
equals()用于验证计算索引处的键是否确实是请求的键。
- 由此可以更清楚地看出为什么不变键比可变键更好。不可变的键将始终保持相同的
hashCode()
值,并且哈希函数将再次找到正确的存储桶(= hashMap的数组中的索引)。
这并不意味着可变键无法工作。如果键上的突变不影响哈希码,或者只要使用hashMap,键就不会发生突变,那么可变键就可以工作。
不变密钥如何更改?好吧,键本身可能无法更改,但是键值映射可以在业务逻辑中更改。如果使用地址作为键来创建地图,那么您将依赖商店地址不会更改的事实。如果商店的地址发生变化,您将不会以其新地址作为关键字在地图上找到它。您的经理有一个有效的观点。
在Map中查找键的速度很大程度上取决于计算hashCode的速度。对于字符串,此计算将遍历字符串中的所有字符。如果将长字符串用作键并具有大量的Map访问权限,则可能会导致性能瓶颈。因此,Java的String实现会缓存哈希值,因此它将仅计算一次。但是,只有
String
再次使用同一实例时,您才避免计算哈希码(新实例将不具有缓存的值)。您可以intern()
使用所使用的密钥,但是只有在可以证明确实存在性能瓶颈的情况下,才考虑使用此密钥,因为String
实习确实会带来自己的开销。如1中所述:如果可变键的哈希码不受突变影响,则可变键可以工作。例如,使用Customer作为键(
hashCode()
仅基于客户名称),然后仅允许名称不更改而允许其他值更改的Customer实现是可靠的键。



