【问题标题】:Why is getEntry(Object key) not exposed on HashMap?为什么 getEntry(Object key) 没有暴露在 HashMap 上?
【发布时间】:2010-12-24 19:19:51
【问题描述】:

这是我的用例,我有一个对象在逻辑上等于我的 HashMap 键,但不是同一个对象(不是 ==)。我需要从 HashMap 中获取实际的关键对象,以便我可以对其进行同步。我知道我可以迭代 ketSet,但与散列相比这很慢。

查看 java.util.HashMap 实现,我看到了一个 getEntry(Object key) 方法,这正是我所需要的。知道为什么这没有被曝光吗?

你能想出别的办法吗?

【问题讨论】:

  • 你可以通过反射得到它,如果没有其他方法,你仍然可以使用。
  • 逻辑上等于 = 等于方法被覆盖? HashMap 总是使用 equals 而不是 ==。通常不鼓励使用可变对象作为键类。
  • @Geo:我会怀疑使用反射来获取要同步的对象;部分是因为性能问题,但主要是因为非常量对象上的显式同步无论如何都很难理解,更不用说通过反射不透明地获取该引用。它可能非常难以理解、遵循和调试,使维护成为一场噩梦。
  • 是的,这是我的问题。我有一个对象 myobject.equals(key) == true 但 myobject == key 返回 false。我需要拿到关键对象。
  • @Geo:获取 HashMap 实现内部的方法或对象不是一个好主意。 HashMap 的内部结构不是 Java 的公共 API 的一部分,可能会在 Java 的未来版本中发生变化,或者 HashMap 可能在其他供应商的 HashMap 实现中实现完全不同。

标签: java concurrency hashmap


【解决方案1】:

我认为你最好在值上添加一层额外的间接层。键也应该是“纯”值。而不是:

Map<ReferenceObjectKey,Thing> map;

用途:

Map<ValueObjectKey,ReferenceObject<Thing>> map;

【讨论】:

  • 这可能不一定是这里的问题 - 例如,String 密钥仍会导致上面声明的相同问题(除非您 interned 所有字符串,这是一个坏主意) ;而且我从来没有听过有人说字符串是不合适的映射键。
  • 我不关注。 Strings 是我书中的价值对象。
  • 我是说字符串和其他值对象仍然存在问题;您提出的解决方案无法解决问题(除了提问者提出的问题不是无论如何都需要解决的问题)。
【解决方案2】:

除了相当明显的“因为作者决定不公开它”之外,我无法回答您的实际问题(为什么不公开该方法)。

但是您的问题使我相信您正在进行一个相当奇怪的同步方案;据我了解,您只是想调用它来获得用于同步的相等对象的规范表示。正如我在对该问题的评论中指出的那样,这听起来是一个非常糟糕的主意。

更好的方法是重新审视您希望在这些关键对象上同步的方式和原因,并重新进行同步以更清晰、更理智,最好在更高级别或完全使用替代方法。

如果您发布代码 sn-p 来说明您希望对此同步执行什么操作,这样其他人可以就更简洁的实现方式发表意见,这可能会有所帮助。一个示例就是使用线程安全的映射类(例如 ConcurrentHashMap),如果这确实是您想要在此处实现的目标。

编辑:看看How To s The Smart Way,特别是我链接的项目符号,因为这是该缺陷的典型示例。您的整体设计似乎有点偏离,需要朝不同的方向发展;因此,当您被困在这个特定问题上时,这是一个更大问题的征兆。为我们提供更广泛的背景将使您获得更好的整体答案。

【讨论】:

    【解决方案3】:

    实际上,调用者要求的方法会很有用。可以说,它或类似的东西没有被包括在内是一个错误。

    事实上,假设您希望增加从键“a”映射的整数值——您最终不得不对“a”进行两次哈希查找。假设您想区分不存在的值和存在但映射为 null 的值——同样,两次哈希查找。

    但实际上,世界并没有因此而终结。

    【讨论】:

      【解决方案4】:

      我最近自己最近偶然发现了这个问题。当我将问题归结为足够多时,我实际上是在使用 2 种不同的方法将数据与用于确定相等性的关键对象部分相关联。

      • 通过映射将键映射到的值
      • 使用密钥对象中包含的数据,但未在 .equals()/hashCode 方法中使用,通过组合。

      我在键类中使用 List 来确定相等性和哈希码,其中还有 3 个其他字段 - 一个布尔值和 2 个字符串。最后,我将地图重新​​制作为 Map, ...> 并将其他 3 个字段重构为自己的类,然后将原始类作为 List 和新类的组合。我觉得在这之后代码看起来更好。

      【讨论】:

        【解决方案5】:

        这听起来像是您遇到的更深层次的问题。你为什么需要这样的东西?为什么它的对象的键不是唯一的?

        “所以我可以同步它”是什么意思?

        【讨论】:

        • 我怀疑希望所有调用相同的对象(即映射到相同的键 within 哈希映射),访问一致的对象实例用于同步。询问者没有说明他为什么要这样做,但这听起来像是在尝试阻止两个线程同时修改给定键的映射。
        • 我认为你是对的。使用 ConcurrentHashMap 可以解决他的问题,如果关于问题的假设当然是正确的:)
        【解决方案6】:

        很抱歉,您在这里似乎有一个概念上的突破。

        如果您的问题是您“持有”一个等效对象(.equals() 为真但 == 为假)到一个键,并且需要找到该键,使用 get 的 Object 变体对您没有帮助,因为 Object 支持的唯一 .equals 是身份 (==)。

        您需要做的是在您的密钥类中实现equals(),当然还有hashcode()。

        这将使获取条目变得微不足道。

        【讨论】:

        • 当然我已经实现了equals和hashcode。我的问题表明
        猜你喜欢
        • 2015-09-26
        • 1970-01-01
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 2018-02-16
        • 1970-01-01
        • 2018-12-25
        相关资源
        最近更新 更多