![](/img/trans.png)
[英]Java int array to HashMap<Integer, Boolean> with IntStream
[英]Java HashMap with Int Array
我正在使用此代码来检查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})));
}
}
但这会打印False
。 如何检查HashMap
是否存在数组?
问题是因为两个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
引用equals
,则可以坚持使用您拥有的内容。 正如您不应该期望上面的代码片段打印true
,您也不应该期望能够仅通过数组的值找到数组; 您必须每次都坚持并使用原始参考资料。Object.equals
和Object.hashCode
您正在比较两个不同的参考。 像这样的事情会起作用:
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()
调用中。
我会使用不同的方法。 如前所述,问题在于数组相等,它基于引用相等并使您的地图无法满足您的需求。 另一个潜在问题,假设您使用 ArrayList 代替,是一致性问题:如果在将列表添加到映射后更改列表,您将遇到哈希映射损坏,因为列表的位置将不再反映其哈希码。
为了解决这两个问题,我会使用某种不可变列表。 例如,您可能想要在 int 数组上制作一个不可变的包装器,并自己实现 equals() 和 hashCode()。
我认为问题在于您的数组正在进行“==”比较,即它正在检查引用。 当您执行 containsKey(new int[] { ... }) 时,它正在创建一个新对象,因此引用不相同。
如果您将数组类型更改为ArrayList<Integer>
应该可以工作,但是我倾向于避免使用 Lists 作为映射键,因为这不会非常有效。
数组的hashCode()
实现派生自Object.hashCode()
,因此它取决于数组的内存位置。 由于这两个数组是分别实例化的,因此它们具有不同的内存位置,因此具有不同的哈希码。 如果您制作了一个数组,它将起作用:
int[] arr = {1, 2};
map.put(arr, "sun");
System.out.println(map.containsKey(arr));
你有两个不同的对象,它们碰巧包含相同的值,因为你已经调用了两次 new 。
您可能使用的一种方法是创建您自己的“持有者”类,并定义该类的 equals 和 hash 方法。
您确定不想将Strings
映射到数组而不是相反吗?
无论如何,要回答您的问题,问题是您在调用containsKey()
时正在创建一个new
数组。 这在你有两个单独的new
ed 数组之间返回 false,它们碰巧具有相同的元素和维度。 请参阅 Yuval 的回答以查看检查数组是否包含为键的正确方法。
另一种更高级的方法是创建您自己的类来包装一个数组并覆盖hashCode()
以便具有相同维度和元素的两个数组将具有相同的哈希码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.