如何深入分析比较Java中的HashMap?针对这个问题,本文详细介绍了相应的分析和解决方法,希望能帮助更多想要解决这个问题的朋友找到更简单易行的方法。
在Java的世界里,类的结构或者各种数据的处理是整个程序逻辑和性能的关键。我接触到一个关于性能和逻辑共存的问题,于是开始研究这个问题。
让我们在这里研究HashMap。
HashMap可以说是JDK的一大功臣。它映射了所有对象,实现了键值对应的快速访问。但是里面到底做了什么?
在此之前,让我们介绍一下负载系数和容量的属性。我们都知道一个HashMap的实际容量是因子*容量,它的默认值是16 0.75=12。这个很重要,肯定会影响效率!当HashMap中存储的对象超过这个容量时,HashMap将重建访问表。这是一个很大的问题,后面我会慢慢介绍。无论如何,如果你已经知道你想要存储多少对象,你最好将它设置为一个可接受的实际容量数。
两个关键方法,放和拿:
首先,有一个概念,HashMap声明了Map、Cloneable、Serializable接口,并继承了AbstractMap类。事实上,里面的迭代器主要是由它的内部类HashIterator和其他几个迭代器类实现的。当然还有一个非常重要的Entry内部类继承了Map.Entry,既然大家都有源代码,有兴趣可以看看这部分。我主要想解释一下Entry内部类。它包含哈希、值、键和next四个属性,这四个属性非常重要。put的源代码如下
公共对象放入(对象键,对象值){ 0
对象k=maskNull(键);
这是判断键值是否为空,不是很深奥。事实上,如果它是空的,它将返回一个静态对象作为键值,这就是为什么HashMap允许空键值。
int hash=hash(k);
int i=indexFor(hash,table . length);
这两个连续的步骤是HashMap最好的部分!学习后,我很惭愧。hash就是通过Object键的hashcode进行散列,然后通过indexFor得到Object表中的索引值。
桌子?别惊讶。事实上,HashMap哪儿也去不了。它被放在一张桌子里。最好的是hash可以正确返回索引。其中我联系了《JDK》的作者豆豆,他建议我看一下《The art of programing vol3》。可恨的是我之前一直在找,却找不到。他这样一提,我就更着急了。不幸的是,我的口袋空了!
不知道大家有没有注意到,put其实是一个没有回报的方法。它会用相同的键值覆盖put并返回旧值!下面的方法彻底说明了HashMap的结构,它实际上是一个表的链表加上相应位置的Entry:
for(条目e=表[I];e!=nulle=e . next){ 0
if (e.hash==hash eq(k,e . key)){ 0
Object oldvalue=e.value
e.value=值;//将新值赋给相应的键值。
e.recordAccess(这个);//空方法,留给实现。
返回oldvalue//返回相同键值对应的旧值。
}
}
modCount//结构变化次数
addEntry(hash,k,value,I);//添加新元素是关键!
返回null//没有返回相同的键值。
}
我们来分析一下关键方法:
void addEntry(int hash,Object键,Object值,int bucket tindex){ 0
表[bucketIndex]=新条目(哈希、键、值、表[bucketIndex]);
因为hash的算法可能会让不同的键值有相同的hash码和相同的表索引,比如key=“33”和key=Object g的hash都是-8901334,那么indexfor之后的索引就必须都是I,这样这个Entry的下一个新的时候就会指向原来的表[i],下一个也是一样的,形成一个链表,和put循环对齐。在这里,HashMap的结构大家都很了解,对吧?
If (size=threshold) //此阈值为实际容量。
调整大小(2 * table . length);//超过此容量,将重建对象表。
所谓重构不是神,就是建一个两倍大的表(我在其他论坛看到有人说是二加一,骗了我),然后一个一个的索引给它!注意!这就是效率!如果能让你的HashMap不需要重构那么多次,效率会大大提高!
差不多了。get比put简单得多。每个人都知道付出和得到没有太大区别。对于收藏品,我认为它适合广泛的范围。当它不完全适合一个独一无二的时候,如果每个人的程序都需要一个特殊的用途,那就自己写吧,其实很简单。(这是作者告诉我的,他还建议我用LinkedHashMap。看完源代码,发现LinkHashMap实际上继承了HashMap,然后覆盖了对应的方法,有兴趣的同事,自己找)。建立一个Object表,写相应的算法,就可以了。
比如Vector、list等东西其实很简单,最多有很多同步语句。事实上,如果你想实现像Vector这样的东西,几乎不需要插入和删除,你可以使用Object表来实现,通过索引访问,添加等等。
如果有许多插入和删除,您可以构建两个对象表,然后将每个元素存储在具有下一个结构的表中。如果你想插入I,但我已经有元素了,用next连接它们,然后调整大小,并在另一个表中记录它的位置。
关于如何深入分析和比较Java中的HashMap的问题的答案将在这里分享。希望
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/138379.html