详谈Map的key、value值的数据类型不能为基本类型的原因

网友投稿 265 2022-11-21


详谈Map的key、value值的数据类型不能为基本类型的原因

interface Map

Map源码

/**

* Returns the hash code value for this map entry. The hash code

* of a map entry e is defined to be:

* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^

* (e.getValue()==null ? 0 : e.getValue().hashCode())

*

* This ensures that e1.equals(e2) implies that

* e1.hashCode()==e2.hashCode() for any two Entries

* e1 and e2, as required by the general

* contract of Object.hashCode.

*

* @return the hash code value for this map entry

* @see Object#hashCode()

* @see Object#equals(Object)

* @see #equals(Object)

*/

int hashCode();

hashCode返回 (e.getKey()==null ? 0 : e.getKey().hashCode()) ^(e.getValue()==null ? 0 : e.getValue().hashCode())

class HashMap extends AbstractMap implements Map, Cloneable, Serializable

HashMap源码中:

public finaqFVHPl int hashCode() {

return Objects.hashCode(key) ^ Objects.hashCode(value);

}

static final int hash(Object key) {

int h;

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

public final boolean equals(Object o) {

if (o == this)

return true;

if (o instanceof Map.Entry) {

Map.Entry,?> e = (Map.Entry,?>)o;

if (Objects.equals(key, e.getKey()) &&

Objects.equals(value, e.getValue()))

return true;

}

return false;

}

补充知识:java hashmap key long 和int 区别

最近同事问起,map里面存的key 是int 类型的,存了一个 Integera =123,为什么使用long 123 作为key get,取出来的是空,这个问题粗想了一下,感觉long和int 本身 类型不同,肯定不能是同一个key,后来细研究了一下,跟了一下源码,发现逻辑不是那么简单。

简单测试了一下,如下代码

Map<Object,String> map = new HashMap<>();

Integer b = 123;

Long c =123L;

map.put(b, b+"int");

System.out.println(b.hashCode() == c.hashCode()); //true

System.out.println(maqFVHPp.get(c)); //null

map.put(c, c+"long"); // size =2

简单的总结了一下问题:

1、HashMap 是把key做hash 然后作为数组下标,但是 b 和c 的hashcode 竟然是相同的,为什么 get(c) 为空

2、HashMap 存入c 发现 size=2 ,hashcode相同 为什么 size=2,get(c) =123long

带着上面两个问题跟了一遍源码,问题豁然开朗

1、hashmap在存入的时候,先对key 做一遍 hash,以hash值作为数组下标,如果发现 下标已有值,判断 存的key 跟传入的key是不是相同,使用 (k = p.key) == key || (key != null && key.equals(k)) ,如果相同覆盖,而Interger的equals 方法如下:

if (obj instanceof Integer) {

return value == ((Integer)obj).intValue();

}

return false;

Integer 和 Long 肯定不是一个类型,返回 false,这时候 hashmap 以 hashkey 冲突来处理,存入链表,所以 Long 123 和 Integer 123 hashmap会认为是 hash冲突

2、hashmap 在 get的时候,也是先做 hash处理,根据hash值查找对应的数组下标,如果找到,使用存入时候的判断条件

(k = first.key) == key || (key != null && key.equals(k)) 如果相等就返回,不相等,查找当前值的next有没有值,有继续根据逻辑判断,所以 存入Integer 123 根据 Long 123 来获取返回的 是 NULL

至此,解析完毕。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较
下一篇:Java springboot项目jar发布过程解析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~