-1

I need to store object type of class edge as Key and ArrayList as Value

public class edge {
    String edgeType;  // Horizontal or Vertical edge
    int i;            //i and j for a cell in 2D matrix
    int j;
}
HashMap<edge, ArrayList<String>> edgeHM = new HashMap<edge, ArrayList<String>>();

Each key's value Arraylist is initialized with 0 and 1

When I retrieve and edit one of the entries using the function reduceEdgeDomain multiple keys get updated with the value. Hash Collision? Eg. need to update Key H21, keys updated H21 and V21 (edgetype, i, j)

H22 <-> V22 or V53 <-> H53

public static void reduceEdgeDomain(HashMap<edge, ArrayList<String>> edgeHM, ArrayList<edge> nonEssEdges){
        ArrayList<String> tempAL;
    for(int i=0; i<nonEssEdges.size(); i++)
    {
        edge str = nonEssEdges.get(i);
        if(edgeHM.containsKey(str)){

            tempAL = edgeHM.get(str);
            edgeHM.remove(str);
            tempAL.remove("1");
            edgeHM.put(str, tempAL);

        }
    }
}

override methods for equals() and hashcode()

public boolean equals(Object o){
        if (this == o){
            return true;
        }

        if(!(o instanceof edge)){
            return false;
        }

        edge edge = (edge) o;
        return i==edge.i && j==edge.j && Objects.equals(edgeType, edge.edgeType);
    }

    @Override
    public int hashCode() {
        String uniqueIdentified = edgeType + i + j;
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        byte[] hash = digest.digest(uniqueIdentified.getBytes(StandardCharsets.UTF_8));
        ByteBuffer wrapped = ByteBuffer.wrap(hash); // big-endian by default
        short num = wrapped.getShort();
        return num;

    }
Sangram Badi
  • 4,054
  • 9
  • 45
  • 78
  • 3
    This makes absolutely no sense. First, I don't see how, based on the code above, you determine that there is a hash collision. Second, hash collisions are expected and normal. All that will cause is a tiny efficiency reduction because the map will have to iterate through a linled list of 2 elements instead of just one. Trying to avoid that by implementing hashCode() using a cryptographic hashing algorithm will make things much much much worse. Computing a crypto hash is several orders of magnitude slower than looping through a list of 2 or 3 elements. – JB Nizet Nov 01 '16 at 08:43
  • 2
    You don't show where you populate the HashMap, but my guess is you are adding the same `ArrayList` instance as a value for multiple keys. – Eran Nov 01 '16 at 08:44
  • 1
    If you have multiple keys pointing to the same List, then updating the value via one key will also appear to update the value via another key because they are the same value. What you describe has nothing to do with hashCodes. BTW It is highly unlikely you need a hashCode which is this complicated and expensive. – Peter Lawrey Nov 01 '16 at 08:44
  • Yes. That was it! I was cracking my head on hash for past few hours. Didn't think about the array list. Thank you... – GagandeepR Nov 01 '16 at 09:08
  • 1
    It is ridiculous overkill to use a MessageDigest as a hash code. – user207421 Nov 01 '16 at 09:17

2 Answers2

1

You are using a short as your hash. There are only 65536 short values so you might just be unlucky. Also as @JBNizet pointed out the use of SHA-256 is not very useful here and will make your code much much slower.

Benedikt Bünz
  • 648
  • 7
  • 22
1

So What? , hash collisions are normal because there are infinite number of possible combination and permutation for string, because string length is infinite, but hashcode in java is "int" which have limited range, so there is nothing to worry about. Hashcode collisions are normal.

Nikesh Joshi
  • 824
  • 6
  • 17