java - 字符串作为 HashMap 中的键

标签 java

<分区>

在过去的一个小时里,我看了很多帖子,但对于在 Hashmap 中使用不可变对象(immutable对象)作为键的概念,我仍然不是很清楚。我有一个 hashmap,它的键是一个字符串。 HashMap 中的值是 MyStore,其中 MyStore 表示有关我拥有的商店的信息。 String 代表地址。在我的代码中,我的逻辑是,我首先在映射中查找该键,如果存在——> 获取它的值,如果它不存在,则将其放入 hashmap 中。我的经理刚刚告诉我 key 将来会改变,也就是说我的商店地址将来会改变。他说,那样的话,我先检查 key 是否存在的逻辑是行不通的。我不明白他在这里的意思。我想非常清楚地了解以下几点 -

  1. HashMap 的可变键和不可变键之间的区别。
  2. 如果您使用可以更改的不可变 key 会怎样? - 我知道这没有意义,但我想清楚地了解我的经理在这里说的是什么。
  3. 一些帖子讨论了字符串如果用作 HashMap 中的键来缓存它们的哈希码——这是什么意思?
  4. 如果假设我在实现哈希码和等值的 HashMap 中使用可变对象作为键,那么它会起作用吗?我假设它会,因为如果 key 发生变化,contains 方法将查看 key 是否存在。如果它不存在,它将放置该条目,以便您将来可以获取它。

如果之前已经讨论过,我并不是要创建一个重复的帖子。如果我错过了阅读回答我所有问题的帖子,请指出它。如果没有,请通俗易懂地解释我的上述问题,以便将来对其他读者有用:)。请随意编辑我的帖子主题,以便将来如果有人有类似问题,他们可以直接登陆这里:)

最佳答案

首先:HashMap 是如何工作的?

基本上它有一个数组,当您将键值对放入映射中时,它会存储在数组中的一个位置。数组中的位置是根据键的 hashCode() 传递给散列方法的结果来选择的。这是为什么?好吧,如果您请求某个键的值,则可以简单地重新计算数组中查找键及其关联值的索引,以再次找到数组中的索引。 (需要更多逻辑来处理映射到同一索引的键,但我只是想让你理解基 native 制)然后使用 equals() 来验证键是否在计算出的索引处确实是请求的键。

  1. 由此应该更清楚为什么不可变键优于可变键。不可变键将始终保持相同的 hashCode() 值,并且哈希函数将再次找到正确的桶(= hashMap 数组中的索引)。

    这并不意味着可变键不能工作。如果键上的突变不影响哈希码,或者只要使用 hashMap 键就不会发生突变,则可变键将起作用。

  2. 不可变 key 如何更改?好吧,键本身可能无法更改,但是键值映射可以在业务逻辑中更改。如果您创建一个 map ,使用地址作为键,您依赖商店地址不会改变的事实。如果一家商店的地址发生变化,您将无法使用其新地址作为关键字在 map 中找到它。你的经理有一个有效的观点。

  3. 在 Map 中查找键的速度很大程度上取决于计算 hashCode 的速度。对于字符串,此计算会遍历字符串中的所有字符。如果您使用长字符串作为键并且有很多 Map 访问权限,这可能会导致性能瓶颈。因此,Java 的 String 实现缓存了散列值,因此它只会被计算一次。但是,如果您再次使用相同的 String 实例,您只会避免计算哈希码(新实例将没有缓存值)。您可以 intern() 您使用的键,但只有在可以证明确实存在性能瓶颈时才考虑这一点,因为 String interning 确实有它自己的开销。

  4. 如 1 中所述:如果哈希码不受突变影响,可变键就可以工作。例如使用 Customer 作为键,其中 hashCode() 仅基于客户的名称,那么仅不允许更改名称但允许更改其他值的 Customer 实现是可靠的键。

关于java - 字符串作为 HashMap 中的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18029983/

相关文章:

java - 大写单词和字符 java 匹配

Java - HttpUrlConnection 每次都返回缓存的响应

java - 我的 CustomDeserializer 类在同一类的第二个字段上第二次不起作用

java - Swagger 专家提供

java - 如何将 java ArrayList 转换为数组?

java - 无法在未调用 Looper.prepare() 的线程内创建处理程序

java - 如何使用Jsoup正确提取所需的信息?

java - 如何配置 spring-boot 项目与内存空间数据库一起进行测试?

java - 从 Web 服务响应中删除时区

java - 如何防止密码重新生成?