nidomiro
nidomiro

Reputation: 830

java: Object1 & Object2 same as Object2 & Object1

I try to draw lines between different GridPositions(x,y). Every GridPos has 4 Connections North, East, South, West. The Problem is if I paint a line from GridPos(1,1) to GridPos(2,2) the program will paint also a line in reverse direction between GridPos(2,2) and GridPos(1,1) later.

I tried to solve the problem with this class (WarpGate is the same as GridPos):

public class GateConnection {

private WarpGate gate1 = null;
private WarpGate gate2 = null;

public GateConnection(WarpGate gate1, WarpGate gate2) {
    super();
    this.gate1 = gate1;
    this.gate2 = gate2;
}

@Override
public int hashCode() {
    final int prime = 31;

    int result = prime * ((gate1 == null) ? 0 : gate1.hashCode());
    result += prime * ((gate2 == null) ? 0 : gate2.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    GateConnection other = (GateConnection) obj;
    if ((gate1.equals(other.gate1) || gate1.equals(other.gate2)) && (gate2.equals(other.gate2) || gate2.equals(other.gate1))) {
        return true;
    }
    return false;
}

}

This Class could be added to an HashSet and the double painting would be gone but I don't know if the hashValue is always unique.

HashCode of WarpGate (auto-generated by eclipse):

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + gridX;
    result = prime * result + gridY;
    return result;
}

For now I use an ArrayList. I look if the GateConnection exists, if not then add. But this version takes much more ressources than using a HashSet.

EDIT:

The white rectangles are the connections which are painted, the numbers are the GridPositions(x|y) and the red Arrows are the two directions the rectangle is painted because GridPos(2|2) has a connection to GridPos(4|2) and (4|2) to (2|2) enter image description here

Upvotes: 1

Views: 576

Answers (1)

ᴇʟᴇvᴀтᴇ
ᴇʟᴇvᴀтᴇ

Reputation: 12751

A TreeSet neither uses hashCode() nor equals(). It uses compareTo(), though you should ensure it is consistent with equals() to respect Set semantics.

For a HashSet, the hashCode() of a stored object does not have to be unique. In fact, you can return the same code for every item if you want and they will still be stored without losing any items, if your equals() is implemented correctly. A good hashCode() will improve performance only.

The only critical rule is that two equal items must generate the same hash code.

Your implementation looks OK as long as you can guarantee that gate1 and gate2 are never equal within the same GateConnection object. If they are equal, two GateConnection objects could have different hash codes but be reported as equal. That would lead to unpredictable behaviour if they are stored in a HashSet.

E.g. GateConnection((1,1), (1,1)) equals GateConnection((1,1), (7,9)) but the hash codes are different.

Upvotes: 2

Related Questions