我有两个HashMaps。 mapA.keySet()
是mapB.keySet()
的子集。我想打印mapA.get(key) != mapB.get(key)
的每个键。但是下面的代码中出现了一些奇怪的行为:
private static void printMissingNums(int[] a, int[] b) {
Map<Integer, Integer> mapA = intArrToMap(a);
Map<Integer, Integer> mapB = intArrToMap(b);
Set<Integer> missingNums = new TreeSet<Integer>();
for (int key : mapA.keySet()) {
//This version does not work!
if (mapA.get(key) != mapB.get(key)) {
missingNums.add(key);
}
/* This version works (if I comment out the if statement above
and remove the comments around this block of code)
int valA = mapA.get(key);
int valB = mapB.get(key);
if (valA != valB) {
missingNums.add(key);
}
*/
}
// Unrelated to the strange behavior
for (int key : mapB.keySet()) {
if (!mapA.containsKey(key)) {
missingNums.add(key);
}
}
for (int i : missingNums) {
System.out.print(i + " ");
}
}
当我使用第一个if语句并且想要了解幕后发生的事情/为什么它不能正常工作时,我会遇到奇怪的行为。对于我有权访问的特定输入,它会打印3个名为x,y,z的数字。我检查了HashMaps并找到mapA.get(x) != mapB.get(x)
和mapA.get(y) != mapB.get(y)
但mapA.get(z) == mapB.get(z)
。
我尝试在if语句之前和之后打印值,并且值相等,但它以某种方式进入if语句。
注释掉的版本按预期工作。它只打印出x和y。怎么了?为什么看起来HashMap值正在变化,即使我没有改变任何东西?
以下是输入:http://pastebin.com/JyYxspjx。第一行是第一个数组中的元素数,后跟空格分隔的整数。 之后的下一行是第二个数组中的元素数,后跟空格分隔的整数。
8622是唯一具有相同值但比较为假的键?
答案 0 :(得分:1)
请勿使用==
,!=
进行对象比较。请改为使用equals()
。
流动的2整数是不同的对象:
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1==i2);//false
将if语句更改为:
if (mapA.get(key).equlas(mapB.get(key))) {
答案 1 :(得分:1)
比较(==
与foo.equals(Obj obj)
)之间的差异基于对象的equals()方法的特定实现。运算符==
表示same object
,在默认情况下,.equals()执行相同的比较。您必须覆盖equals方法才能更改此默认行为。
在Java Integer类中,它会覆盖equals方法,将行为从same object
更改为等同原始值:
// From the java source
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
在这里你可以看到Integer类实际上是比较类类型然后比较原始值是否相等。在这种情况下,Integer == Integer比较不同比Integer.equals(整数)比较。
如果您感到好奇,Java Object
类等于实现是:
// From the Java source code
public boolean equals(Object obj) {
return (this == obj);
}
因为一切都最终扩展了java中的Object类,所以你总是得到同样的对象&#34; for equals除非你的类或继承的类重写equals方法。
在侧节点上,如果您曾覆盖&amp;实现等于你自己,一定要覆盖&amp;同时实现哈希码(大多数IDE都会为此生成自动代码,如果你选择另一个则不会发出警告)。覆盖equals时不覆盖哈希码的结果意味着你的HashMap / HashSet集合可能找不到&#34;等于&#34; map / set中的对象,因为它不一定会散列到同一个桶中。
另一种方法是使用Set操作方法。如果您不关心对底层地图的修改,您可以执行以下操作:(请记住,这实际上会修改键集/底层地图)
Set<Integer> uniqKeysInA = mapA.keySet().removeAll(mapB.keyset())
如果您关心修改/维护原件,您需要使用mapA的密钥集的防御性副本进行操作:
Set<Integer> uniqKeysInA = (new HashSet<Integer>(mapA.keySet())).removeAll(mapB.keySet())