带有Int数组的Java HashMap

Sun*_*il 16 java arrays hashmap

我正在使用此代码来检查HashMap中是否存在该数组.

public class Test {
    public static void main(String[] arg) {
        HashMap<int[], String> map = new HashMap<int[], String>();
        map.put(new int[]{1, 2}, "sun");
        System.out.println(map.containsKey((new int[]{1, 2})));
    }
}
Run Code Online (Sandbox Code Playgroud)

但这打印错误.如何检查HashMap中是否存在该数组.提前致谢.

pol*_*nts 30

问题是因为两者int[]不相等.

System.out.println(
    (new int[] { 1, 2 }).equals(new int[] { 1, 2 })
); // prints "false"
Run Code Online (Sandbox Code Playgroud)

Map和其他Java Collections Framework类根据其定义其接口equals.来自Map API:

Collections Framework接口中的许多方法都是根据equals方法定义的.例如,对于在本说明书中containsKey(Object key)的方法表示:"返回true当且仅当此映射包含一个键的映射关系k,使得(key==null ? k==null : key.equals(k))".

请注意,它们不必是同一个对象; 他们只需要equals.Java中的数组扩展自Object,其默认实现equals仅在对象标识上返回true; 因此,为什么它打印false在上面的代码片段.


您可以通过多种方式解决问题:

  • equals使用其方法的数组定义自己的包装类. java.util.Arrays equals/deepEquals
    • 不要忘记,当你@Override equals(Object),你也必须@Override hashCode
  • 使用类似List<Integer>的是没有定义equals在它们所包含的价值观方面
  • 或者,如果你可以使用引用相等equals,你可以坚持你拥有的.就像你不应该期望上面的代码段打印一样true,你不应该期望能够仅通过其值来找到你的数组; 你必须每次都挂上并使用原始参考文献.

也可以看看:

API

  • Object.equalsObject.hashCode
    • 对于Java程序员来说,了解这些合同以及如何使它们与系统的其余部分一起工作至关重要


Yuv*_*dam 8

您正在比较两个差异参考 - 请注意双重使用new.这样的东西会起作用:

public class Test {
    public static void main(String[] arg)
    {
     HashMap<int[],String> map= new HashMap<int[],String>();
     int[] a = new int[]{1,2};
     map.put(a, "sun");
     System.out.println(map.containsKey(a));
    }
}
Run Code Online (Sandbox Code Playgroud)

由于a是相同的参考,您将按true预期收到.如果你的应用程序没有选择传递引用来进行比较,我会创建一个包含int[]和覆盖equals()方法的新对象类型(不要忘记同时覆盖hashCode()),这样就会反映在containsKey()调用中.

  • 仅实现`equals()`不够**,你也需要实现`hashCode()`.请参阅Effective Java的第3章(可在线获取:http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf) (5认同)