ArrayList增长时,具有ArrayList键的HashMap找不到它



我的问题是,在代码的某些部分,我使用arraylist作为哈希图中的键,例如

ArrayList<Integer> array = new ArrayList<Integer>();

然后我把我的数组像一个键一样放在哈希图中(我需要它,我确信这一点)

HashMap<ArrayList<Integer>, String> map = new HashMap<ArrayList<Integer>, String>();
map.put(array, "value1");

问题来了:当我给数组添加一些值,然后我试图使用相同的数组恢复数据时,哈希图找不到它。

array.add(23);
String value = map.get(array);

此时值为null,而不是字符串"value1"我在测试时发现,当数组列表增加时,hashCode会发生变化,这是我问题的核心,但我想知道如何解决这个问题。

使用IdentityHashMap。然后,无论其内容(以及哈希代码)如何更改,相同的数组实例都将始终映射到相同的值。

不能使用可变对象(即hashCode发生变化的对象)作为HashMap的键。看看你是否能找到其他东西作为钥匙。将集合映射到字符串有些不寻常;另一种方式更为常见。

这是一个奇怪的用例,但如果必须这样做,则可以对数组进行子类并覆盖hashCode方法。

在我看来,这是一件需要尝试和做的事情。

我假设您试图建模的是一个由n整数组成的可变长度密钥,并假设ArrayList的哈希是一致的,但我不确定情况是否如此。

我建议您将ArrayList子类化并覆盖hash()&equals()方法或将HashMap封装在密钥类中。

我几乎可以肯定你不会想这么做。你更可能想要Map<String, List<Integer>>。但是,如果您绝对必须这样做,请使用holder类:

public class ListHolder {
    private List<Integer> list = new ArrayList<Integer>();
    public List<Integer> getList() {return list;}
}
Map<ListHolder, String> map = new HashMap<ListHolder, String>;

基本原因:当我们使用HashMap.put(k,v)时,它会对k.hashCode()进行数字运算,这样它就可以知道放在哪里了。

它还通过这个数字(k.hashCode())找到值;

您可以看到ArrayList.hashCode()函数,它位于AbstractList的抽象类中。显然,在我们添加一些对象之后,它将更改haseCode值。因此,我们无法使用HashMap.get(K)找到值,并且没有hashCode是K的元素。

public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

最新更新