Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique hashCode with two fields without order

Tags:

java

hashcode

I need a hashCode implementation in Java which ignores the order of the fields in my class Edge. It should be possible that Node first could be Node second, and second could be Node first.

Here is my method is depend on the order:

public class Edge {
    private Node first, second;

    @Override
    public int hashCode() {
        int hash = 17;
        int hashMultiplikator = 79;
        hash = hashMultiplikator * hash
                + first.hashCode();
        hash = hashMultiplikator * hash
                + second.hashCode();
        return hash;
    }
}

Is there a way to compute a hash which is for the following Edges the same but unique?

Node n1 = new Node("a");
Node n2 = new Node("b");
Edge ab = new Edge(n1,n2);
Edge ba = new Edge(n2,n1);

ab.hashCode() == ba.hashCode() should be true.

like image 490
veote Avatar asked Jun 10 '13 06:06

veote


2 Answers

You can use some sort of commutative operation instead of what you have now, like addition:

@Override
public int hashCode() {
    int hash = 17;
    int hashMultiplikator = 79;
    int hashSum = first.hashCode() + second.hashCode();
    hash = hashMultiplikator * hash * hashSum;
    return hash;
}

I'd recommend that you still use the multiplier since it provides some entropy to your hash code. See my answer here, which says:

Some good rules to follow for hashing are:

  • Mix up your operators. By mixing your operators, you can cause the results to vary more. Using simply x * y in this test, I had a very large number of collisions.
  • Use prime numbers for multiplication. Prime numbers have interesting binary properties that cause multiplication to be more volatile.
  • Avoid using shift operators (unless you really know what you're doing). They insert lots of zeroes or ones into the binary of the number, decreasing volatility of other operations and potentially even shrinking your possible number of outputs.
like image 162
Brian Avatar answered Sep 25 '22 20:09

Brian


To solve you problem you have to combine both hashCodes of the components.

An example could be:

@Override
public int hashCode() {
    int prime = 17;
    return prime * (first.hashCode() + second.hashCode());
}

Please check if this matches your requirements. Also a multiplikation or an XOR insted of an addition could be possible.

like image 43
Uwe Plonus Avatar answered Sep 23 '22 20:09

Uwe Plonus