0

I'm attempting to generate a maze using a version of Kruskal's algorithm. I need to check if some coordinates (in an int[] array, eg [1, 5]) are in an existing set.

Here is a copy of the part of the code;

// find sets containing cells to be joined
for (HashSet<int[]> h : cells) {
    if (h.contains(new int[]{x, y - 2})) {
        set1 = h;
    }
}

The issue is that the if statement is never true, but I'm 99.9% sure it should be true at least once.

Am I using HashSet.contains() wrong?

Thanks

3 Answers3

1

Am I using HashSet.contains() wrong?

Well, you have an expectation which is wrong, but it's more about arrays than about HashSet. Arrays in Java don't implement equals and hashCode in the way it looks like you're expecting them to. They effectively exhibit reference equality behaviour. For example:

int[] array1 = { 1 };
int[] array2 = { 1 };
System.out.println(array1.equals(array1)); // true - same reference
System.out.println(array1.equals(array2)); // false - different reference

Rather than using an int[] for coordinates, I'd suggest creating a Coordinate class with x and y fields. If that Coordinate class then overrides equals and hashCode appropriately, then using HashSet will work. (Although I'd advise creating the object you're looking for outside the loop rather than in each iteration.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

HashSet contains() Method in Java util. HashSet contains() method is used to check whether a specific element is present in the HashSet or not. So basically it is used to check if a Set contains any particular element.

Ng Sharma
  • 2,072
  • 8
  • 27
  • 49
0

I think this will help:

Stream.generate(() -> new int[] { 1, 2 }.hashCode()).limit(3).forEach(System.out::println);

notice we're printing the hashcode of [1, 2] three times but we get three unique values. That is because each new int[] has a different hashCode(). Create a custom type, override hashCode and add that to your HashSet. Something like

public class Cell {
    private final int x, y;

    public Cell(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public int hashCode() {
        return 13 ^ x ^ y;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        } else if (this == o) {
            return true;
        } else if (o instanceof Cell) {
            Cell c = (Cell) o;
            return this.x == c.x && this.y == c.y;
        }
        return false;
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 2
    I would advise making the `Cell` (or `Coordinate`) class immutable. Aside from anything else, mutating the object in a hashcode-affecting way after it's been added to a `HashSet` will break the expectations of `HashSet`. – Jon Skeet Nov 29 '19 at 10:58