Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java hashmap在调用containsKey()时检查什么? ArrayList lis=new ArrayList(); 增加(2); 增加(3); ArrayList lis2=新的ArrayList(); lis2.添加(2); lis2.添加(3); HashMap=newHashMap(); 地图放置(lis,7); System.out.println(map.containsKey(lis2));_Java_Hashmap_Hashtable_Containskey - Fatal编程技术网

Java hashmap在调用containsKey()时检查什么? ArrayList lis=new ArrayList(); 增加(2); 增加(3); ArrayList lis2=新的ArrayList(); lis2.添加(2); lis2.添加(3); HashMap=newHashMap(); 地图放置(lis,7); System.out.println(map.containsKey(lis2));

Java hashmap在调用containsKey()时检查什么? ArrayList lis=new ArrayList(); 增加(2); 增加(3); ArrayList lis2=新的ArrayList(); lis2.添加(2); lis2.添加(3); HashMap=newHashMap(); 地图放置(lis,7); System.out.println(map.containsKey(lis2));,java,hashmap,hashtable,containskey,Java,Hashmap,Hashtable,Containskey,最初,我希望代码打印出“false”,因为lis和lis2是不同的对象。 令人惊讶的是,代码打印出“true”。hashmap在调用containsKey()时检查什么?它检查.hashCode以找到bucket,然后使用.equalsList.equals返回true如果所有元素的顺序相同并且也是.equalsArrayList.hashCode将为具有相同元素的两个ArrayList实例返回相同的值,因此它会找到正确的bucket,然后使用.equals并查看列表的元素是否相同且顺序相同 例

最初,我希望代码打印出“false”,因为lis和lis2是不同的对象。
令人惊讶的是,代码打印出“true”。hashmap在调用containsKey()时检查什么?

它检查
.hashCode
以找到bucket,然后使用
.equals
List.equals
返回
true
如果所有元素的顺序相同并且也是
.equals
ArrayList.hashCode
将为具有相同元素的两个
ArrayList
实例返回相同的值,因此它会找到正确的bucket,然后使用
.equals
并查看列表的元素是否相同且顺序相同

例如:

    ArrayList<Integer> lis = new ArrayList<Integer>();
    lis.add(2);
    lis.add(3);
    ArrayList<Integer> lis2 = new ArrayList<Integer>();
    lis2.add(2);
    lis2.add(3);
    HashMap<ArrayList<Integer>, Integer> map = new HashMap<ArrayList<Integer>, Integer>();
    map.put(lis, 7);
    System.out.println(map.containsKey(lis2));
这是因为添加另一个元素更改了
lis.hashCode()
的值。当您
put
列表时,使用
hashCode
拾取一个bucket。通过添加新元素,您可以更改它将使用的bucket,但不会更改您已经添加到地图中的条目的bucket。除此之外:

map.put(lis, 7);
lis.add(3);
System.out.println(map.get(lis)); // Prints "null", *not* "7"
它第二次解析为不同的bucket,因此它将其视为第二个元素

在这种情况下,您可以使用
Collections.unmodifiableList
来“冻结”列表,添加它,然后再也不要触摸它:

map.put(lis, 7);
lis.add(3);
map.put(lis, 7);
System.out.println(map.size()); // Prints "2"
然后,如果稍后调用
get()。添加(3)


这将抛出一个
不支持操作异常

这是因为lis和lis2的哈希代码相等

lis2.hashCode()==lis.hashCode()为true

源代码(HashMap)中的方法包含skey,如下所示:

map.get(7).add(3);
/**
*如果此映射包含
*指定的密钥。
*
*@param key此映射中存在的密钥将被测试
*@如果此映射包含指定对象的映射,则返回true
*钥匙。
*/
公共布尔containsKey(对象键){
对象k=maskNull(键);
int hash=hash(k.hashCode());
int i=indexFor(散列,table.length);
条目e=表[i];
while(e!=null){
if(e.hash==hash&&eq(k,e.key))
返回true;
e=e.next;
}
返回false;
}

您将哈希映射定义为

/**
 * Returns <tt>true</tt> if this map contains a mapping for the
 * specified key.
 *
 * @param   key   The key whose presence in this map is to be tested
 * @return <tt>true</tt> if this map contains a mapping for the specified
 * key.
 */
public boolean containsKey(Object key) {
    Object k = maskNull(key);
    int hash = hash(k.hashCode());
    int i = indexFor(hash, table.length);
    Entry e = table[i]; 
    while (e != null) {
        if (e.hash == hash && eq(k, e.key)) 
            return true;
        e = e.next;
    }
    return false;
}
HashMap map=newhashmap();
因此,键是一个整数列表,值是一个整数

map.containsKey(lis2)将尝试为给定的键查找匹配项。因此,将在每个键上调用equals方法。由于键实际上是一个整数列表,因此将按顺序对该列表的每个项调用equal方法

这就是为什么输出是正确的


如果更改第二个列表中的任何项目,甚至更改项目的顺序,则输出将为false。

map.containsKey
如果此映射包含指定键的映射,则返回
true
。它使用
键的
equals
方法检查是否相等:

HashMap<ArrayList<Integer>, Integer> map = new HashMap<ArrayList<Integer>, Integer>();
如果(从ArrayList doc复制)出现以下情况,则称两个ArrayList相等:

比较指定对象与此列表是否相等。退换商品 当且仅当指定对象也是列表时为true,两个列表 具有相同的大小,且所有对应的两个元素对 名单是平等的。(如果(e1==null,则两个元素e1和e2相等。)? e2==null:e1.equals(e2)))换句话说,两个列表被定义为 如果它们包含相同顺序的相同元素,则表示相等

此实现首先检查指定的对象是否在此列表中。 如果是,则返回true;如果不是,则检查指定的对象是否为 列表如果不是,则返回false;如果是这样,它将在两个列表上迭代, 比较对应的元素对。如果有比较返回 false,此方法返回false。如果任一迭代器的 元素之前的其他元素返回false(如列表所示) 长度不等);否则,在迭代时返回true 完成


由于这两个列表包含相同顺序的相同数量的元素,因此它们被认为是
相等的
,这就是
map.containsKey(lis2)
返回
true

的原因。它首先检查hashCode(),以便知道在哪里查找要调用相等的对象。我对此表示异议。请看下面的答案MouseLearnJava@Peter修正了,也增加了关于可变键的更新(biiiig no no),它还检查
eq(k,e.key)
调用中的
equals
/**
 * Returns <tt>true</tt> if this map contains a mapping for the
 * specified key.
 *
 * @param   key   The key whose presence in this map is to be tested
 * @return <tt>true</tt> if this map contains a mapping for the specified
 * key.
 */
public boolean containsKey(Object key) {
    Object k = maskNull(key);
    int hash = hash(k.hashCode());
    int i = indexFor(hash, table.length);
    Entry e = table[i]; 
    while (e != null) {
        if (e.hash == hash && eq(k, e.key)) 
            return true;
        e = e.next;
    }
    return false;
}
HashMap<ArrayList<Integer>, Integer> map = new HashMap<ArrayList<Integer>, Integer>();
key != null && key.equals(k)