Moosh
Moosh

Reputation: 63

HashMap in Java

I had an interview today, and I got the following Java code:

public class Question_6 {
    public static void main(String[] args){
        Map<Integer,String> map1 = new HashMap<Integer,String>();
        map1.put(new Integer(1),"001a");
        map1.put(new Integer(1),"001b");
        map1.put(new Integer(2),"002");

        System.out.println(map1.size());

        Map<MyInt,String> map2 = new HashMap<MyInt,String>();
        map2.put(new MyInt(1),"001a");
        map2.put(new MyInt(1),"001b");
        map2.put(new MyInt(2),"002");

        System.out.println(map2.size());

    }

}
public class MyInt {
    int i;
    public MyInt(int i) {
       this.i = i;
    }

}

The questions were:

  1. What will be printed to the console?

  2. Suggest a solution to the problem.

I know now that the answer to the first question is :

2

3

But I don't know why? What is the problem with MyInt?

Upvotes: 4

Views: 8743

Answers (8)

Neelesh Aggarwal
Neelesh Aggarwal

Reputation: 1

For the Integer class, By Default The Integer class caches integer values from -127 to 127. Therefore, the Integer objects can only be created in the range -128 to 127.

map1.put(new Integer(1),"001a");// new entry created in hashmap map1.put(new Integer(1),"001b");// "001b" overrides "001a" value in hashmap map1.put(new Integer(2),"002");// new entry created in hashmap

So overall size of hashmap will be 2.

Upvotes: 0

Narendra Reddy
Narendra Reddy

Reputation: 162

The Integer class overrides the equals() method to do value-based comparison.No need to manually include equals() or hashcode() methods. My solution is as follows

import java.util.HashMap;
import java.util.Map;

    public class HashMapEqualsHashcode {

        public static void main(String[] args) {

            MyInt obj = new MyInt(50);

            Map<Integer, String> map1 = new HashMap<Integer, String>();

              map1.put(new Integer(1),"001a");
              map1.put(new Integer(1),"001b");
              map1.put(new Integer(2),"002");

            System.out.println("map1 size "+map1.size());

            Map<MyInt,String> map2 = new HashMap<MyInt,String>();
            map2.put(new MyInt(1),"001a");
            map2.put(new MyInt(1),"001b");
            map2.put(new MyInt(2),"002");

            System.out.println("map2 size "+map2.size());
        }
    }

     class MyInt {
        int i;
        public MyInt(int i) {
           this.i = i;
        }



    }

Screenshot for the solution

https://i.sstatic.net/yVkgL.png

Upvotes: 1

Anubhav Mishra
Anubhav Mishra

Reputation: 125

The Integer class overrides the equals() method to do value-based comparison. Hashmaps cannot contain two keys that are "equal", so the 2nd insertion into map1 will overwrite the first entry. As well, the hashcode() method is overridden.

However, Myint does not override the equals() or hashcode() method so equality is memory location-based. Therefore, map2 sees three distinct keys and makes three distinct entries.

Upvotes: 0

gaborsch
gaborsch

Reputation: 15758

Your problem is that equals() and hashcode() is not implemented on MyInt.

You are expected to have 2 as a result in both cases.

HashMap, as the name implies, groups the keys into buckets based on the keys' hashcode(). But the default hashcode does not match for two instances of MyInt with the same value.

To determine equality, you have to override equals() as well.

One solution:

public class MyInt {

    [...]

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

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof MyInt) {
            return i == ((MyInt)obj).i;
        }
        return false;
    }

}

Upvotes: 12

stinepike
stinepike

Reputation: 54722

You must override the hashCode() and equals methods. For all cases where equals returns true for two objects, hashCode returns the same value. The hash code is a code that must be equal if two objects are equal

Why??

if you inspect in the source code of HashMap.put method. you can see that this method check both hashcode and equality before inserting. So if you don't override these methods it will use the superclass' (object's) methods which will return different values for different objects. So ALthough for the same key two values will be inserted in separate place of Hashmap. So you need to override those two and make sure that for two equal objects you should return same hashcode.

Code

So your MyInt should be something like

public class MyInt {
    int i;
    public MyInt(int i) {
       this.i = i;
    }        

    public int hashCode() {
       return i;
    }    

    public boolean equals(Object obj) {
        if (obj instanceof MyInt && i == ((MyInt)obj).i) {
            return true;
        } else
            return false;
    }
}

Upvotes: 0

oguzhancerit
oguzhancerit

Reputation: 1572

map1.put(new Integer(1),"001a");
        map1.put(new Integer(1),"001b");//same location in map
        map1.put(new Integer(2),"002");

in this part you use the Integer class, Integer class don't allow setting the same location, but your Integer class allow.

Change code like this, and you see the problem

public class Question_6 {
    public static void main(String[] args){
        Map<Integer,String> map1 = new HashMap<Integer,String>();
        map1.put(new Integer(1),"001a");
        map1.put(new Integer(2),"001b");
        map1.put(new Integer(3),"002");

        System.out.println(map1.size());

        Map<MyInt,String> map2 = new HashMap<MyInt,String>();
        map2.put(new MyInt(1),"001a");
        map2.put(new MyInt(2),"001b");
        map2.put(new MyInt(3),"002");

        System.out.println(map2.size());

    }

this code will print ;

3 3

So, your Integer class(myInt) is true but missing

Upvotes: 1

waldol1
waldol1

Reputation: 1881

The Integer class overrides the equals() method to do value based comparison. Hashmaps cannot contain two keys that are "equal", so the 2nd insertion into map1 will overwrite the first entry. As well, the hashcode() method is overridden.

However, MyInt does not override the equals() or hashcode() method so equality is memory location based. Therefore, map2 sees three distinct keys and makes three distinct entries.

    Map<MyInt,String> map2 = new HashMap<MyInt,String>();
    MyInt one = new MyInt(1);
    MyInt two = new MyInt(2);
    map2.put(one,"001a");
    map2.put(one,"001b");
    map2.put(two,"002");

    System.out.println(map2.size());

Produces an output of 2 in this case because one.equals(one) is true in this case.

Upvotes: 2

AllTooSir
AllTooSir

Reputation: 49422

You need to override the equals() and hashCode() method in your MyInt class , so that HashMap can comprehend new MyInt(1).equals(new MyInt(1)) is true.

Upvotes: 3

Related Questions