Question

Main Question
I have a hashmap filled with vertex objects. Based on an integer (i.e. 1), I want to find that vertex object. See the code below:

public class Playground {

    public static void main(String[] args) {
        Map<Vertex, String> map1 = new HashMap<Vertex, String>();
        Map<Integer, String> map2 = new HashMap<Integer, String>(); 

        Vertex v1 = new Vertex(5);
        map1.put(v1, "1");
        Vertex v2 = new Vertex(5);
        String s = map1.get(v2);
        System.out.println(s);

        Integer int1 = new Integer(1);
        map2.put(int1, "2");
        Integer int2 = new Integer(1);
        String t = map2.get(int2);
        System.out.println(t);
    }
}

class Vertex{

    public int id;

    public Vertex(int id){
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        Vertex v = (Vertex) obj;

        return (this.id == v.id);
    }
}

Output:
null
2

As you see above, it works with the Integer object but not the user-defined Vertex object. I overrid the equals method as well.

Addition Information I have a text file. The first column denotes the tail of an edge. The second the head of an edge. Here is an excerpt:
1 1
1 2
1 8
1 4
2 47646
2 47647
...

I pre-load the vertices 1 - n because...well...I cannot check the keyset of my map each time to see if the vertex already exists.
Anyway, so then, based on this text file, I need to locate the vertex with id "x" and add an edge.

You might be inclined to ask why I don't use Integer objects as keys instead. Numerous examples online used generic V objects and it makes sense --- each node (irl) would have extra information, whether a stop's name or whatever.

Was it helpful?

Solution

You need to override the hashCode method to make the JVM store and retrieve your objects in HashMap properly.

When a put method is called on a hashed collection such as HashMap, the key object hashcode method is called to decide the bucket to store the object. Then its equals method is called to see whether something already exist there or not.

Similary when you do a get on the HashMap, key hashCode method will be called to find the bucket and to retreive the object.

As you have not overridden the hashcode method in your Vertex class so defualt hashcode implemenataion is used. And hence two your Vertex objects having the same id value may be having a different hashcode.

Read this related post to understand how to override the equals and hashcode method:

What issues should be considered when overriding equals and hashCode in Java?

You can find different articles on google for the same topic. A good google result:

http://javarevisited.blogspot.in/2011/02/how-to-write-equals-method-in-java.html

OTHER TIPS

You need to add hashCode() method and fix your equals() in your Vertex class

Try this:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Vertex vertex = (Vertex) o;

        if (id != vertex.id) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return id;
    }

Maps use hashCode() to determine which object matches the request. equals() is used by Comparable classes. No two objects can be guaranteed to be identical, even if the supplied properties are equal.

The reason it works with Integer objects is because the Integer class is simply a wrapper around the primitive int type, and every other property/method of the Integer class is identical to another Integer object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top