如何在哈希映射中使用对象数组作为键

huangapple go评论72阅读模式
英文:

How to use an Object array as a key in hashmap

问题

我有一个名为 Position[] 的对象数组,它返回一个 Position 对象的数组。我想将其用作哈希映射的键,如下所示:HashMap<Position[],Double> h = new HashMap<>();

我理解,即使元素相同,数组也会有不同的哈希码。所以我尝试重写 equals 和 hashcode 方法。这是我的尝试:

public class Key {
    private Position p1;
    private Position p2;

    public Key(Position p1, Position p2){
      this.p1 = p1;
      this.p2 = p2;
    }

    @Override
    public boolean equals(Object object) {
      if (!(object instanceof Key)) {
        return false;
      }

      Key newKey = (Key) object;
      return this.hashCode() == newKey.hashCode(); //有点取巧的方式
    }

    @Override
    public int hashCode(){
      int result = 17;
      result = 31 * result + this.p1.hashCode();
      result = 31 * result + this.p2.hashCode();
      return result;
    }
  }

所以我不得不将我的映射更改为 HashMap<Key,Double>,然而,每当我使用键获取值时仍然返回 null。

Key 构造函数中可以传递的示例为 G2 G4E4 E6 等。

我该如何实现才能使比较真正起作用呢?

谢谢。

英文:

I have an object array called Position[] that returns an array of Position objects. I would like to use this as my key for a hashmap for the following: HashMap<Position[],Double> h = new HashMap<>();

I understand that arrays have different hashcodes even if the elements are the same. So I went ahead and tried to override the equals and hashcode. This was my attempt:

public class Key {
    private Position p1;
    private Position p2;

    public Key(Position p1, Position p2){
      this.p1 = p1;
      this.p2 = p2
    }

    @Override
    public boolean equals(Object object) {
      if (!(object instanceof Key)) {
        return false;
      }

      Key newKey = (Key) object;
      return this.hashCode()== newKey.hashCode(); //bit of a hack way
    }

    @Override
    public int hashCode(){
      int result = 17;
      result = 31 * result + this.p1.hashCode();
      result = 31 * result + this.p2.hashCode();
      return result;
    }
  }

So I had to change my map to HashMap<Key,Double> However, when ever i go to get the value using the key is still returns null.

An example of what can be passed into they constructor of Key are G2 G4 or E4 E6 ETC.

How would I go about achieving this so that the comparisons actually work?

Thanks.

答案1

得分: 1

你可以创建一个特殊的包装对象,使用Arrays.deepEquals(Object[], Object[])Arrays.deepHashCode(Object[])来实现equals(Object)hashCode()方法,将Position[]作为Map中的键。

import java.util.Arrays;

public final class PositionArrayKey {
    private final Position[] array;

    public PositionArrayKey(Position[] array) {
        this.array = array;
    }

    @Override
    public boolean equals(Object object) {
        if (object == this) return true;
        if (!(object instanceof PositionArrayKey)) return false;
        return Arrays.deepEquals(this.array, ((PositionArrayKey) object).array);
    }

    @Override
    public int hashCode() {
        return Arrays.deepHashCode(this.array);
    }
}

这样可以将经过包装的Position[]数组实例作为键存储在映射中,例如:

Map<PositionArrayKey, Object> map = new HashMap<>();
map.put(new PositionArrayKey(new Position[]{...}), ...);
Object value = map.get(new PositionArrayKey(new Position[]{...}), ...);

(假设在此示例中,两个Position[]数组在深度上是相等的)

请注意,对于大型数组,调用equals(Object)hashCode()可能会导致性能下降。如果有必要,你可以修改上述代码片段,为较大的数组缓存Arrays.deepHashCode(this.array)的结果。

英文:

You can create a special wrapper object to use Position[] as a key in a Map, using Arrays.deepEquals(Object[], Object[]) and Arrays.deepHashCode(Object[]) in the implementations of equals(Object) and hashCode().

import java.util.Arrays;

public final class PositionArrayKey {
    private final Position[] array;

    public PositionArrayKey(Position[] array) {
        this.array = array;
    }

    @Override
    public boolean equals(Object object) {
        if (object == this) return true;
        if (!(object instanceof PositionArrayKey)) return false;
        return Arrays.deepEquals(this.array, ((PositionArrayKey) object).array);
    }

    @Override
    public int hashCode() {
        return Arrays.deepHashCode(this.array);
    }
}

This enables storing Position[] array instances as keys in map, when wrapped. E.g.

Map&lt;PositionArrayKey, Object&gt; map = new HashMap&lt;&gt;();
map.put(new PositionArrayKey(new Position[]{...}), ...);
Object value = map.get(new PositionArrayKey(new Position[]{...}), ...);

> (assuming that both of the Position[] arrays are deeply equal in this example)

Note that for large arrays, performance for invoking equals(Object) and hashCode() may be slow. You can modify the above snippet to cache the result Arrays.deepHashCode(this.array) for larger arrays, if you find it necessary.

huangapple
  • 本文由 发表于 2020年10月15日 07:22:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64362783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定