IdentityHashMap NullPointerException

时间:2014-09-15 16:21:29

标签: java nullpointerexception hashmap

我遇到了一个问题。我使用了IdentityHashMap。我将这些条目放入其中{150 = 1,79 = 3,345 = 6,88 = 5,50 = 4,3 = 7,24 = 2}。当密钥为50,150时,我试图获取它们的值。但是我得到了java.lang.NullPointerException。我不知道为什么。请帮我修理一下。非常感谢你。

这是我的代码:

 import java.util.IdentityHashMap;
 import java.util.Arrays;
 public class HelloWorld {
     public static int[] twoSum(int[] numbers, int target) {
            int[] result = new int[2];
            if (numbers == null || numbers.length < 2) {
                return result;
            }

            IdentityHashMap<Integer, Integer> map = new IdentityHashMap<Integer, Integer>();
            for (int i = 0; i < numbers.length ; i++) {
                map.put(numbers[i], i+1);
            }

            Arrays.sort( numbers );

            int head = 0;
            int tail = numbers.length - 1;
            while (head < tail) {
                if (numbers[head] + numbers[tail] == target) {

                    result[0] =  map.get( numbers[head] );
                    result[1] =  map.get( numbers[tail]i );
                    return result;
                } else if (numbers[head] + numbers[tail] < target) {
                    head++;
                } else {
                    tail--;
                }
            }
            return result;

        }
      public static void main(String[] args) {
        int[] sorce = {150,24,79,50,88,345,3};
        twoSum(sorce, 200);

    }

}

1 个答案:

答案 0 :(得分:3)

您将被自动装箱整数时自动使用的JVMs int缓存池捕获。结果是低int值将共享一个盒装int的相同实例,但更大的值将不会。 150超出此缓存范围,因此插入到地图中的密钥与用于查看值的实例不同。

作为证据,请运行以下代码:

    Integer a = 150;
    Integer b = 150;

    System.out.println("System.identityHashCode(a) = " + System.identityHashCode(a));
    System.out.println("System.identityHashCode(b) = " + System.identityHashCode(b));

可以预期两个值都具有相同的标识哈希码,但它们不会。在我的测试运行中,输出是:

System.identityHashCode(a) = 1291472364
System.identityHashCode(b) = 1158801519

引用涵盖此行为的JLS 5.1.7

  

理想情况下,装箱给定的原始值p将始终产生相同的参考。实际上,使用现有的实现技术可能不可行。上述规则是一种务实的妥协。上面的最后一个条款要求将某些常见值装入无法区分的对象中。实现可以懒惰地或急切地缓存这些。对于其他值,此公式不允许对程序员的盒装值的身份进行任何假设。这将允许(但不要求)共享部分或全部这些引用。

要解决此问题,您应该完全避免自动装箱。但是正如另一个证明正是这个缓存会让你感到困惑,你可以在运行测试时调整int缓存的大小。

-Djava.lang.Integer.IntegerCache.high=4096

设置此标志后,您的测试程序将不会抛出NullPointerException,并且将按照您预期的方式运行。最高不超过4096的关键值;)