How to use an Object array as a key in hashmap

Viewed 108

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 Answers

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<PositionArrayKey, Object> map = new HashMap<>();
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.

Related