java – hashmap在调用containsKey()时检查什么?

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));

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

解决方法

它检查.hashCode以查找存储桶,然后使用.equals.如果所有元素的顺序相同且也是.equals,则List.equals返回true. ArrayList.hashCode将为具有相同元素的两个ArrayList实例返回相同的值,因此它找到正确的存储桶,然后使用.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);
System.out.println(lis.equals(lis2)); // Prints "true"

值得注意的是,您永远不应该使用可变对象作为HashMap中的键.通过修改密钥,可以使其所在的存储桶无效.例如,如果我这样做:

map.put(lis,7);
lis.add(3);
System.out.println(map.get(lis)); // Prints "null",*not* "7"

这是因为添加一个元素会更改lis.hashCode()的值.放置列表时,hashCode用于选择存储桶.通过添加新元素,您可以更改它将使用的存储桶,但不会更改已添加到地图的条目的存储桶.添加到上面:

map.put(lis,7);
lis.add(3);
map.put(lis,7);
System.out.println(map.size()); // Prints "2"

它第二次解析为另一个桶,因此它将其视为第二个元素.

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

map.put(Collections.unmodifiableList(lis),7);

然后,如果你调用get().add(3):

map.get(7).add(3);

这将抛出UnsupportedOperationException.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...