HashMap是线程不安全的,存储的值没有顺序,根据key的HashCode值来存储数据,根据key来获取他的value值,具有很快的访问速度。
最多只允许一个key值为Null,多个时会覆盖,允许多条记录的Value为null。
底层数据结构:
在JDK1.7中,由数组和链表组成,数组是HashMap的主体,链表是为了解决哈希冲突。
在JDK1.8中,由数组+链表+红黑树组成,链表过长的时候,影响HashMap性能,JDK8中,链表超过8并且数据总量超过64就会转红黑树,转之前会判断,如果数组长度小于64就会选择先进行数组扩容。
HashMap的存储过程:
HashMap<String,String> h=new HashMap<String,String> ();
h.put("你好","世界");//Key-Value形式
存储数据的时候,首先通过hashCode方法得到key的哈希码,经过hash方法得到hash值,这个值用来定位这个元素的位置,数组默认长度为16,用hashCode值对16求余就得到了一个数组下标,如果下标对应位置是空的,直接存进去,如果不是空的,就去使用equals比较两个元素是否相等,相等就直接覆盖,不相等就就在这个元素下面使用链表的结构存储该数据,每个节点都有一个next属性指向下一个节点,也就由数组结构变成了数组+链表的结构,如果链表中元素太多的话,影响查询效率,如果链表元素个数达到8并且数组长度达到64的时候,就转成红黑树存储(红黑树是平衡二叉树,查找性能比链表高),数组长度小于64会进行数组扩容。
hashCode是Object类中的一个方法,该方法用native修饰,所以是一个本地方法,所谓本地方法就是非java代码,这个代码通常用c或c++写成,在java中可以去调用它。调用这个方法会生成一个int型的整数,我们叫它哈希码,哈希码和调用它的对象地址和内容有关.
HashMap扩容:
我们创建一个HashMap的集合对象,底层node数组默认大小是16,当集合的存储容量达到一个临界值的时候会扩容,loadFactor * capacity (负载因子 * 容量),负载因子默认是0.75。
怎么判断两个HashMap相等?
首先,hashcode相等--->hashcode算的快,然后是equals相等。
hash相等两个对象,并不一定完全相等;但是两个对象相等,hashcode一定相等。