我遇到了一个问题。我使用了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);
}
}
答案 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的关键值;)