【问题标题】:How can I use a third party Class Object as Hashmap Key?如何使用第三方类对象作为 Hashmap 键?
【发布时间】:2014-08-07 14:54:27
【问题描述】:

好的,我了解equals 和hashcode 的工作原理以及它们在hashmap 中的使用方式。 但是我想到了这个问题,如果我有一个第三方对象没有覆盖哈希码和等于,我什至不允许修改它。

考虑以下类:

//Unmodifiable class
public final class WannaBeKey{

    private String id;

    private String keyName;

    //Can be many more fields

    public String getId()
    {
          return id;
    }

    public String getKeyName()
    {
          return id;
    }
    //no hashcode or equals :(

  }

现在我想将这个类作为我的 Hashmap 键,显然如果没有 equals 和 hashcode,它将无法工作。我想知道有没有办法处理这种情况?我什么都想不出来,或者我想不通..

谢谢。

【问题讨论】:

  • 它确实有一个 equals 和一个 hashCode - Object
  • 是的,但这并不总是足够好,他可能需要基于 WannaBeKey 的 id 而不是实例的相等性
  • 但是它们在 hashmap 中会失败,因为 Objects equals 方法会检查引用相等而不是内容相等。
  • 如果来自 Object 的那些还不够,那么您可能必须创建一个 decorator
  • 将地图的键设为 id 字符串。

标签: java oop hashmap


【解决方案1】:

我以前遇到过这个问题,并通过为 WannaBeKey 创建一个包装器来解决它:

public class WannaBeKeyWrapper {

  private final WannaBeKey key;


  public WannaBeKeyWrapper(WannaBeKey key) {
    this.key = key;
  } 

  public boolean equals(Object obj) {

    // Insert equality based on WannaBeKey
  }

  public int hashCode() {
    // Insert custom hashcode in accordance with http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
  }
}

显然这会将您的 SetSet<WannaBeKey> 更改为 Set<WannaBeKeyWrapper>,但您应该能够考虑到这一点。

【讨论】:

    【解决方案2】:

    您可以为该对象创建一个包装器,该包装器将具有覆盖的方法。然后你可以使用包装类作为你的哈希映射的键。

    【讨论】:

    • 为什么这被否决了?这是使用 WannaBeKey 作为映射键基础的唯一方法。
    【解决方案3】:

    您可以使用所需的语义将实际对象包装在另一个实例中:

    class KeyWrapper {
    
      WannaBeKey key; // constructor omitted
    
      @Override
      public int hashCode() {
        return key.getId().hashCode();
      }
    
      @Override
      public boolean equals(Object o) {
        // equals method implementation
      }
    }
    

    或者,您可以简单地扩展该类(如果该类不是您在编辑中所述的 final)。

    【讨论】:

    • 这个类也是final的,所以不能扩展它。
    • 然后使用包装方法,正如我提到的那样,无论如何都是更好的解决方案。
    • 虽然我不是 OP。 ;)
    【解决方案4】:

    这个问题已经得到了彻底的回答,但我认为值得一提的是,上述解决方案是称为Decorator 的特定设计模式的一部分。

    Adapter 或 Wrapper 模式使用基本相同的解决方案,但更多用于将代码转换为不同的接口,而装饰器用于扩展。

    【讨论】:

      猜你喜欢
      • 2015-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      相关资源
      最近更新 更多