Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set<Integer> inside Map

Tags:

java

I have a question. First, I declared a map:

Map<TwoIntClass, Set<Integer>> m = new HashMap<TwoIntClass, Set<Integer>>();

Now, I want to put stuff inside this map, something like

int num = 7;
m.put(new TwoIntClass(5, 3), ?? how to put num inside Set ??);

My question is, how do I put variable num inside Set. Thanks.

like image 769
user433947 Avatar asked Nov 30 '22 17:11

user433947


2 Answers

Like Jack and others have suggested, you need to instantiate a concrete instance of the Set interface (like HashSet), add your int values in the Set and then put the Set into your Map. However, if you are using a custom class for your Map's key, I would suggest you implement the equals() and hashCode() method of your TwoIntClass class to be sure that you are not creating duplicate entries inside your Map. For example, consider this class :

public class TwoIntClass {

    private int i1;
    private int i2;

    public TwoIntClass(int i1, int i2) {
        this.i1 = i1;
        this.i2 = i2;   
    }

    static public void main(String...args) {

        Map<TwoIntClass, Set<Integer>> map = new HashMap<TwoIntClass, Set<Integer>>();

        Set<Integer> dataset = new HashSet<Integer>();
        dataset.add(1);
        dataset.add(2);

        TwoIntClass i1 = new TwoIntClass(5, 3);
        TwoIntClass i2 = new TwoIntClass(5, 3);

        map.put(i1, dataset);
        map.put(i2, dataset);

        System.out.println( i1.hashCode() + " = " + i2.hashCode() + " == " + i2.equals(i2) + " > map count = " + map.size() );

        TwoIntClass i3 = new TwoIntClass(5, 3);
        System.out.println("Looking for TwoIntClass(5,3)... " + map.containsKey(i3) );

    }
}

The output for executing it is :

1476323068 = 535746438 == false > map count = 2

Looking for TwoIntClass(5,3)... false

As you see, they both are "equal" (i.e. they both are constructed with the same integers), but they are distinct objects with different hash codes, therefore create two entries in the map. This could lead into possible data corruption in your application. Moreover, executing this line : map.get(new TwoIntClass(5,3)).add(3); will generate a NullPointerException because the key (it's hash) does not exist in the map. So, you need to implement the equals() and hashCode() methods to fix this, so any TwoIntClass constructed with the same integers will be considered equal. Something like :

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof TwoIntClass)) {
        return false;
    }
    TwoIntClass other = (TwoIntClass) obj;

    return (other.i1 == this.i1) && (other.i2 == this.i2); 
}

@Override
public int hashCode() {
    //return TwoIntClass.class.hashCode() | i1 | (i2 << 16);

    // better implementation based on the String class
    int hash = TwoIntClass.class.hashCode();

    hash = (hash * 31) + i1;
    hash = (hash * 31) + i2;

    return hash;
}

yields a more expected result of

1476323071 = 1476323071 == true > map count = 1

Looking for TwoIntClass(5,3)... true

Of course, this hashCode() method is over simplistic and you may need to find a yet better construct, but the bottom line is that implementing them is what I would recommend.

like image 132
Yanick Rochon Avatar answered Dec 05 '22 03:12

Yanick Rochon


Set set = new HashSet();
set.add(2);
set.add(4);
...
m.put(new TwoIntClass(5, 3), set);

Slightly better (from here):

m.put(new TwoIntClass(5, 3), new HashSet(Arrays.asList(1, 2)));

You can modify the set like this:

m.get(new TwoIntClass(5, 3)).add(6);
like image 42
nanda Avatar answered Dec 05 '22 03:12

nanda