2

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.

6
  • 5
    this.hashCode()== newKey.hashCode() ← That will fail eventually. Just use a List<Position> instead of an array. Arrays don’t have useful hash codes, but Lists are guaranteed to have hash codes based on their elements’ hash codes. Commented Oct 14, 2020 at 23:34
  • If you cannot use List instead of arrays, you can get the correct hashcode using the utility class method Arrays.hashCode Commented Oct 14, 2020 at 23:43
  • @VGR Is an ArrayList<Position> possible? or doe sit have to be List<Position> Commented Oct 14, 2020 at 23:49
  • When you create an ArrayList, you can refer to it as a List, or a Collection, or an Iterable, or an Object. It’s good practice to make variables and fields have a type of List or Collection rather than ArrayList, since there are many possible implementations of List (such as LinkedList and Arrays.asList) and you want to have the option of using them. It’s not like you need your List to be an ArrayList in order to use its methods, after all. Commented Oct 14, 2020 at 23:54
  • 1
    Correct. All List implementations in Java SE already implement those methods correctly. Commented Oct 15, 2020 at 0:14

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I think you mean "may be slow" rather than "may not be slow", yes?
@Steve Yes, was a typo. Fixed, thanks for pointing it out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.