数组:存储区间是连续的,且占用内存严重,空间复杂也很大,时间复杂为O(1)。
优点:是随机读取效率很高,原因数组是连续(随机访问性强,查找速度快)。
缺点:插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中要往后移的,且大小固定不易动态扩展。
链表:区间离散,占用内存宽松,空间复杂度小,时间复杂度O(N)。
优点:插入删除速度快,内存利用率高,没有大小固定,扩展灵活。
缺点:不能随机查找,每次都是从第一个开始遍历(查询效率低)。
哈希表是二者结合:
实现查询效率高和插入删除效率也高的数据结构。
HashMap是Map中的一个集合类。
JDK1.7 中,HashMap 采用[数组 + 链表]的结构,即使用链表来处理冲突,同一 hash 值的链表都存储在一个数组中。但是当位于同一个桶中的元素较多,即 hash 值相等的元素较多时,通过 key 值依次查找的效率较低。底层数据结构是一个Entry数组,每个Entry数组中包含一个key-value键值对。Entry数组有三个属性,hash、key、value。
JDK1.8中,HashMap的底层结构发生改变,采用[数组+链表+红黑树]的结构。当每个链表中的元素个数大于8时,会将此链表转化为红黑树,优化查询效率;当红黑树元素个数小于6时,会将红黑树转化成链表。
HashMap默认负载因子是0.75。
当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的搬移到新的数组中。
HashMap,put元素的过程:
将key和value封装近Node节点中,然后调用key的hashCode()方法得出hash值,以此来确定插入元素的位置。如果这个位置上没有任何元素,就把这个节点放到这个位置,如果对应位置有链表,就会把这个key和节点上每一个key进行比较,如不存在相同的就添加到末尾,如果存在,就覆盖。
HashMap,get元素的过程:
先调用key的hashCode()方法得出hash值,之后通过hash值快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着参数key和单向链表上的每一个节点的key进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的key和参数key进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。
和HashTable的区别:(浅)
HashMap允许null键和null值,但HashTable不允许。
HashMap是非同步的,HashTable是同步的。
是否存在key值相同的情况:
HashMap在存入的时候最先比较的是key的hashcode是否相同,所以是存在key值表面相同的情况。
参考文档【1】:来复习一波,HashMap底层实现原理解析 (baidu.com)
参考文档【2】:Java中HashMap底层实现原理(JDK1.8)源码分析_tuke_tuke的博客-CSDN博客_hashmap底层实现原理
ps:因为是个雏,不懂原理,所以这篇文章是借鉴上述两位前辈的文章节选拼凑的。这篇文章如果侵犯您的权益,请及时联系我删除该文章,抱歉!