0

Hopefully I understand the purpose for the HashMultimap in Guava, because if I don't, I'll just downvote myself.

I'm trying to access the Collection from a specific key where the key is a class like so...

public class Coords {

private int[] coords;

public Coords() {
    coords = new int[2];
}

public Coords(int x, int y) {
    coords = new int[] {x, y};
}

public void set(int x, int y) {
    coords = new int[] {x, y};
}

public int x() {
    return coords[0];
}

public int y() {
    return coords[1];
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null || getClass() != obj.getClass())
        return false;

    Coords o = (Coords) obj;

    return Integer.compare(x(), o.x()) == 0 && 
           Integer.compare(y(), o.y()) == 0;
}

When I compare two Coords objects with the same integer values in it's array, I get true.

When I popular the HashMultimap with key/value pairs, I do indeed get a unique set of keys, but I do not get a collection of more than one Item. I get multiple keys that seem to be identical, even though I have overridden the equals() method in Object. When I popular the map...

HashMultimap<Coords, Item> items = HashMultimap.create();

        Item s = new Item();
        s.coords.set(0, 0);
        Item w = new Item();
        w.coords.set(0, 0);

        Item p = new Item();
        p.coords.set(1, 1);

        items.put(s.coords, s);
        items.put(w.coords, w);
        items.put(p.coords, p);

        Collection<Item> bucket = items.get(s.coords);
        bucket.add(s);
        items.putAll(s.coords, bucket);

        bucket = items.get(w.coords);
        bucket.add(w);
        items.putAll(w.coords, bucket);

        bucket = items.get(p.coords);
        bucket.add(p);
        items.putAll(p.coords, bucket);

        for(Coords key : items.keySet()) {
            System.out.println(key.x() + " " + key.y());
        }

I get the output...

0 0
1 1
0 0

What am I missing? Did I implement something incorrectly?

VocoJax
  • 1,469
  • 1
  • 13
  • 19
  • 1
    You need to override hashCode too. Your equals method is never being called because equal Coordinates objects have different hashCodes so are being put into different buckets. – cpp beginner Oct 20 '17 at 02:20
  • 1
    public int hashCode() { return Arrays.hashCode(coords); } – cpp beginner Oct 20 '17 at 02:29

1 Answers1

0

Thanks for all the comments. I actually realized I need to overwrite the hashCode() method shortly after I posted this question. Of course...

But I will explain, for those of you who are stuck on this problem, and don't understand how to implement hashCode() successfully. This question has answers very similar to mine...

Does hashcode implementation of Java Arrays.hashcode() uniformly distribute

But, I ended up implementing hashCode() like this...

@Override
public int hashCode() {
    int hash = 1;
    for (int e : coords)
        hash = 31 * hash + e;

    return hash;
}

Thanks to cpp beginner, I could have used Arrays.hashCode(), but just thought I'd write out something so that I could see it working. So I could better understand the method and what it does.

VocoJax
  • 1,469
  • 1
  • 13
  • 19