1

I have the following code:

payoffs2exchanges.put(point, exchange);
if (!payoffs2exchanges.containsKey(point) ) {
   game.log.fine("yes");
} else {
   game.log.fine("no");
}

It outputs "no". In other words, I add the key-value pair to the map, and then, immediately after that I check if the key exist and find out that it does not exist. Why?

I still have the problem with the key. The following code says every time I add a key I add a new key. And I know that it is not the case.

        Integer[] point = new Integer[2];
        point[0] = proposerBestScore;
        point[1] = responderBestScore;
        game.log.fine("In the getCloudOfPayoffs: found payoffs:" + point[0] + "," + point[1] + ". Exchange: " + exchange[0]+","+exchange[1]+","+exchange[2]+","+exchange[3]+","+exchange[4]);
        // With the following block we ensure that every options (pair of payoffs) is represented by exchange with minimal number of moves.
        if (!payoffs2exchanges.containsKey(point)) {
            payoffs2exchanges.put(point, exchange); 
            game.log.fine("In the getCloudOfPayoffs: this option is new. We add it to the map.");
        } else {
            game.log.fine("In the getCloudOfPayoffs: this option is old.");
            Integer[] exchangeFromMap = payoffs2exchanges.get(point);
            Integer newSum = 0;
            Integer oldSum = 0;
            for (int i=0;i<Design.nColors;i++) {
                newSum = newSum + Math.abs(exchange[i]);
                oldSum = oldSum + Math.abs(exchangeFromMap[i]);
            }
            if (newSum<oldSum) {
                game.log.fine("In the getCloudOfPayoffs: the new exchange is better than the old one.");
                payoffs2exchanges.put(point, exchange);
            }
        }
Roman
  • 124,451
  • 167
  • 349
  • 456

3 Answers3

6

It is doing the right thing. containsKey returns true, the ! operator negates it to false, and so it outputs no (the else clause).

lijie
  • 4,811
  • 22
  • 26
6

You're using an Integer[] as key in the map. This is a bad thing, since Java arrays don't implement equals and hashCode as you might expect. See this example:

public class Test {
    public static void main(String[] args) {
        Integer[] arr1 = { 1, 2 };
        Integer[] arr2 = { 1, 2 };

        System.out.println(arr1.equals(arr2));
        System.out.println(arr1.hashCode() + " / " + arr2.hashCode());
    }
}

On my computer it prints:

false
1476323068 / 535746438

My recommendation is to create a custom Point class that properly overrides equals and hashCode (or possibly reuse java.awt.Point if you think that makes sense).

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • does it mean that containsKey does not work if I use integer array as a key? – Roman Dec 10 '10 at 16:06
  • Yes, exactly. Maps in general rely heavily on the `equals` method, and when it comes to for instance `HashMap` the `hashCode` is important as well. – aioobe Dec 10 '10 at 16:07
  • but can I still use `somHashMap.get(key)` if key is an integer array? – Roman Dec 10 '10 at 16:09
  • No. The `get` method would call `key.hashCode()` to figure out in which bucket to look for the value associated with `key`. If the hash value of `key` doesn't correspond to the hash value of the key used when inserting the element, the hash map will simply (most likely) look for the value in the wrong bucket. – aioobe Dec 10 '10 at 16:12
0

Look at your code :) it prints no if the map actually contains the key...

pgras
  • 12,614
  • 4
  • 38
  • 46