【问题标题】:java.util.HashMap get: does key have to be exactly the same object as what is stored in the HashMap, or can the keys just be "equal"java.util.HashMap 获取:键是否必须与存储在 HashMap 中的对象完全相同,或者键是否可以“相等”
【发布时间】:2017-08-08 20:36:31
【问题描述】:

假设我有一个 HashMap M。我想在这个 HashMap 上调用“get”函数,并找到与给定对象 S 关联的值。但是我没有对对象S 的实际引用,因此我创建了一个新对象S_new,其内容与S 的内容相同。如果我调用M.get(S_new),那会给我与键S 关联的值吗?

【问题讨论】:

  • 绝对不,它们不是同一个实例。
  • 简短答案 - 如果对象相等且具有相同的 hashCode 值,它将正常工作。
  • 如果它们的哈希值相同——是的。如果不是——不。应该避免吗? -- 绝对

标签: java hashmap


【解决方案1】:

来自the documentation for Map#get

public V get(Object key)

返回指定键映射到的值,如果是 null 此映射不包含键的映射。更正式地说,如果这张地图 包含从键k 到值v 的映射,使得(key==null ? k==null : key.equals(k)),则此方法返回v;否则它 返回null。 (最多可以有一个这样的映射。)

只要您传递的参数覆盖 equals 使得映射键被视为等效,您就可以使用不同的实例从映射中检索值。

此外,正如@Eugene 和其他人所提到的,对于HashMap,您还必须覆盖hashCode 方法,并确保您的实例返回与您的键相同的值。一般来说,最佳实践是确保您的相等实现是对称的(即A.equals(B) B.equals(A)),并且相等的值应该具有相同的hashCode

【讨论】:

  • 在基于哈希的映射或集合中,hashCode 也必须被覆盖,否则永远不会测试相等性。
  • OP 要求提供HashMap,因此拥有匹配的hashCode() 方法也很重要。
  • @nbrooks 如果您不覆盖哈希码,那么在 HashMap 的上下文中可能根本找不到该条目...
【解决方案2】:

是的,只要hashcodeequals 产生相同的精确值,它就会产生。还要注意get 甚至不需要参数是T - 它是Object,所以any 类型可以满足哈希码和equals 的工作

【讨论】:

  • 在实践中,任何其他类型都可以兼容地实现equalshashCode,这在不太可能和不可能之间。见this answer
  • @KevinKrumwiede 我同意。我还没有看到从Map 获得除T 以外的其他东西在逻辑上有意义的情况;这仍然是规范允许的......
【解决方案3】:

不使用键从映射中获取值并不意味着键应该与放置时使用的对象相同。

唯一的问题是 hashcode & equals 应该是相同的,这就是如果你想使用自己的类对象作为 key 必须重写 Hashcode & equals 方法的原因。

【讨论】:

    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多