我正在使用此代码检查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})));
}
}
但这会打印出来。 如何检查HashMap中是否存在该数组。 提前谢谢。
答案 0 :(得分:29)
问题是因为两个int[]
不相等。
System.out.println(
(new int[] { 1, 2 }).equals(new int[] { 1, 2 })
); // prints "false"
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
一样,你不应该期望能够仅通过其值来找到你的数组;你必须每次都坚持使用原始参考文献。Object.equals
和Object.hashCode
答案 1 :(得分: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));
}
}
由于a
是相同的引用,您将按预期收到true
。如果您的应用程序没有选择传递引用来进行比较,我会创建一个包含int[]
的新对象类型并覆盖equals()
方法(不要忘记覆盖hashCode()
同时),这将反映在containsKey()
电话中。
答案 2 :(得分:4)
我会使用不同的方法。如前所述,问题在于数组相等性,它基于引用相等性而使您的地图无法满足您的需求。 另一个潜在的问题,假设您使用ArrayList,是一致性的问题:如果在将地图添加到地图后更改列表,则会出现哈希图损坏,因为列表的位置将不再反映其哈希码。
为了解决这两个问题,我会使用某种不可变列表。例如,你可能想在int数组上创建一个不可变的包装器,并自己实现equals()和hashCode()。
答案 3 :(得分:2)
我认为问题是你的数组正在进行'=='比较,即它正在检查引用。当你执行containsKey(new int [] {...})时,它正在创建一个新对象,因此引用不一样。
如果您将数组类型更改为ArrayList<Integer>
应该有效的类型,但我倾向于避免使用Lists作为地图键,因为这不会非常有效。
答案 4 :(得分:2)
数组的hashCode()
实现派生自Object.hashCode()
,因此它取决于数组的内存位置。由于两个数组分别实例化,因此它们具有不同的存储器位置,因此具有不同的哈希码。如果你制作了一个数组,那就可以了:
int[] arr = {1, 2};
map.put(arr, "sun");
System.out.println(map.containsKey(arr));
答案 5 :(得分:1)
你有两个碰巧包含相同值的不同对象,因为你已经调用了两次。
您可能使用的一种方法是创建自己的“holder”类,并定义该类的equals和hash方法。
答案 6 :(得分:1)
您确定不想将Strings
映射到数组而不是相反吗?
无论如何,要回答您的问题,问题是您在拨打new
时正在创建containsKey()
数组。在您有两个具有相同元素和维度的单独new
ed数组之间返回false。请参阅Yuval的答案,以查看检查数组是否作为键包含的正确方法。
另一种更高级的方法是创建自己的包装数组并覆盖hashCode()
的类,以便具有相同维度和元素的两个数组具有相同的哈希码。