1

I have a HashSet in my code that uses a custom type, Line, where Line has four integer fields (x1, y1, x2, y2; all representing coordinates of start and end points of the line). I populate the HashSet with a large number of these Lines. I then want to later remove specific Lines. I tried calling HashSet.remove(new Line(correct properties)), but that failed. Any ideas on how I could go about doing this?

Attached is the code for reference. The class is attempting to implement an Aldous-Broder maze generator, such that initially all walls are populated into the set, and then walls are removed (as the method carves the maze paths), before being passed to the drawing mechanics.

package tests;

import java.util.HashSet;
import java.util.Random;

public class AldousBroderTest {

static HashSet<Line> walls = new HashSet<Line>();
static Random rn = new Random();

public static void generateWalls(int x1, int y1, int x2, int y2){
    for (int i = x1; i < x2; i += 10){
        for (int j = y1; j < y2; j += 10){
            walls.add(new Line(i, j, i + 10, j));
            walls.add(new Line(i,j,i,j+10));
        }
    }
    walls.add(new Line(x1, y1, x1, y2));
    walls.add(new Line(x1, y1, x2, y1));
    walls.add(new Line(x2, y1, x2, y2));
    walls.add(new Line(x1, y2, x2, y2));
}

public static void generateMaze(int x1, int y1, int x2, int y2){
    boolean[][] visited = new boolean[x2-x1][y2-y1];
    int counter = 1;
    int currentx = rn.nextInt((x2-x1)/10)*10;
    int currenty = rn.nextInt((y2-y1)/10)*10;
    visited[currentx][currenty] = true;
    int cellcount = (x2-x1)/10 * (y2-y1)/10;
    System.out.println(cellcount);
    while (counter < cellcount){
        int direction = rn.nextInt(4); 
        switch (direction){
        case 0: 
            if(currenty == y1){break;}
            currenty -= 10;
            if(visited[currentx][currenty] == false){
                visited[currentx][currenty] = true;
                counter++;
                walls.remove(new Line(currentx, currenty+10, currentx+10, currenty+10));
            }
            break;
        case 1:
            if(currentx+10 == x2){break;}
            currentx += 10;
            if(visited[currentx][currenty] == false){
                visited[currentx][currenty] = true;
                counter++;
                walls.remove(new Line(currentx, currenty, currentx, currenty+10));
            }
            break;
        case 2:
            if(currenty+10 == y2){break;}
            currenty += 10;
            if(visited[currentx][currenty] == false){
                visited[currentx][currenty] = true;
                counter++;
                walls.remove(new Line(currentx, currenty, currentx+10, currenty));
            }
            break;
        case 3:
            if(currentx == x1){break;}
            currentx -= 10;
            if(visited[currentx][currenty] == false){
                visited[currentx][currenty] = true;
                counter++;
                walls.remove(new Line(currentx+10, currenty, currentx+10, currenty+10));
            }
            break;
        }
    }
}

public static void main(String[] args){
    generateWalls(0,0,50,50);
    generateMaze(0,0,50,50);
    Frame frame = new Frame(walls);
  }

}
Abdelhak
  • 8,299
  • 4
  • 22
  • 36
fogmike
  • 13
  • 4
  • You are trying to remove a new object? `walls.remove(new Line(currentx, currenty+10, currentx+10, currenty+10));` – Tomaltach Dec 15 '15 at 09:27
  • Does `Line` implement hashcode and equals ? – Mikey Dec 15 '15 at 09:29
  • To explain, yes I was planning on trying to make a new Line with the same properties, to see if that would work. I hadn't realised about overriding the equals method, which makes a lot of sense. – fogmike Dec 15 '15 at 09:40

2 Answers2

6

In class Line, override equals and hascode methods.

@Override
public boolean equals(Object obj) {
    // equals code
}

@Override
public int hashCode() {
    // hascode method
}

And here you can find the explanation of "why to implement these two methods" Why do I need to override the equals and hashCode methods in Java?

Community
  • 1
  • 1
awsome
  • 2,143
  • 2
  • 23
  • 41
  • Ah ok, that makes sense, thank you. Would I need to override hashCode too, or is overriding equals enough? (And to check - equals takes another instance of Line, and returns true if it's equal to the current instance?) – fogmike Dec 15 '15 at 09:34
  • you have to override both, explanation is in linked question, and yes equals takes another instance of Line and returns true or false if the conditions specified in the equals method match or not, read more on link on how to write equals method https://www.artima.com/lejava/articles/equality.html – awsome Dec 15 '15 at 09:40
  • 1
    Edit (Since for some reason SO won't let me edit, I'm new here sorry): Just seen the line I missed with the explanation for needing both, got it now. Thanks! – fogmike Dec 15 '15 at 09:42
0

You're HashSet is hashing the objects as they are added, a new Line(...) call will produce a new object and thus a different hashcode; hence it not working. To remove these you'll have to either keep the original objects and remove using those, or as others have said override equals and hashCode methods in your Line class so that they are based on properties of the object.

jonk
  • 1,494
  • 11
  • 13