导读:
在我们学习数据结构的过程中会理解很多的算法结构,比如说list、link、map等等。这些数据结构都是非常常见的结构,那么反问一下,为什么要发明这些数据结构呢?理由很简单,我们的所有目前的计算机内存都是有限的,那么我们要更好的利用这些内存,得到合理化最大化的利用肯定少不了巧妙的算法设计。所以很简单,如果我们能够学好数据结构会给我们的程序性能优化带来飞一样的进步。当然最难和最需要思维的就是数据结构,努力攻破算法就是胜利。加油吧少年们!!!!fight!!!
一、Hashmap的结构
首先我们都知道HashMap 是一个散列表,它存储的方式是key-value的形式,它是由数组和链表组成的特殊的存储结构。这时候你会问,为什么需要数组和链表组成?我们都知道数据量一旦大的时候,我们总是希望能够在查询的时候一时间就能够锁定我们想要查询的值,这样能够大量的减少我们的查询时间,所以Hashmap结构就诞生了。我们都知道数组是顺序存储的,它的查询的时间复杂度是O(1),链表的查询数据的时间复杂度是O(N),那么Hashmap查询时间复杂度到底是怎么样的呢???其实在这里,我们不考虑链表的查询复杂度O(N),说Hashmap的查询复杂度是O(1)其实也是能够说得通的。
为什么这么说呢?如图所示
这个是我简单做的一个促进理解的图片。可以看到Hashmap的存储结构,现在如果我们如果建一个长度为5的数组,链表长度为20。那么如果存在1-100的顺序数据,散列数据进Hashmap结构中,它们的每一个位置都应该是明确的,比如说30应该在数组第二个空间里的第10个位置,55应该在数组第三个空间里的第15个位置等等。因为我们在进行数组散列的过程中根据数据的大小进行散列,它们每个数据在数组里位置会被散列出一个散列码,这个散列码是用来记住它数组的位置。同时根据Hashmap中的key算出索引,索引获得索引位置所对应的键值对链表,遍历键值对链表,根据key找到对应的Entry键值对,最后拿到value值。
现在明白为什么是近似O(1)了吧,就是在Hashmap中已经归类好每一个空间的可取值范围了,这样根据它的散列码和索引值直接可以定位它的位置了,何尝不是O(1)级别的呢。
那么Hashmap增删改查复杂度如此之低,是不是大家都可以在任何场合都可以用它了呢?首先我们知道Hashmap的会根据一定的条件进行数组分割,让数据根据自己的索引进入链表中,适用场景比如说注册账号信息等,这些少量不需要总是修改和添加的,多读少加的可以考虑使用Hashmap。
同时, HashMap可以接受null键值,HashMap是非synchronized。
二、Hashmap的工作原理
基于哈希原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用LinkedList来解决碰撞问题,当发生碰撞了,对象将会储存在LinkedList的下一个节点中。 HashMap在每个LinkedList节点中储存键值对对象。
当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的LinkedList中。键对象的equals()方法用来找到键值是否符合要求。