<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>-Flyぁ梦- &#187; hash表</title>
	<atom:link href="http://blog.11034.org/tag/hash%e8%a1%a8/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.11034.org</link>
	<description></description>
	<lastBuildDate>Sun, 22 Jun 2025 08:59:05 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>java.util中几个Map的性能测试</title>
		<link>http://blog.11034.org/2013-05/java_map.html</link>
		<comments>http://blog.11034.org/2013-05/java_map.html#comments</comments>
		<pubDate>Mon, 27 May 2013 08:47:35 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[数据结构和算法]]></category>
		<category><![CDATA[hash表]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1786</guid>
		<description><![CDATA[突然有这么个想法，就写了段代码测试了下。在单线程下对Java里所有Map的性能测试，包括HashMap、Has [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>突然有这么个想法，就写了段代码测试了下。在单线程下对Java里所有Map的性能测试，包括HashMap、Hashtable、LinkedHashMap、IdentityMap、TreeMap，没有测试WeakHashMap。</p>
<p>数据为&lt;Integer, Integer&gt;，范围在0~1千万，共1百万对数据，由Python的random.randint()自动生成。</p>
<p>测试的性能包括写入（put）、随机读（get）和遍历（foreach语法），也是Map这个数据结构最常用的三个操作。其中写入就是将这1百万对测试数据依次put一遍，随机读就是在上一步写入之后再按顺序get一遍。数据显示最后Map大小都为995012（当然IdentityMap的size是1百万），就是有近5000条重复的key。<br />
<span id="more-1786"></span></p>
<p>下面是笔记本上跑出的数据：</p>
<p align="center">Java中各个Map的性能测试（T400笔记本，酷睿P8700/2.46G）数据表</p>
<div align="center">
<table border="0" cellspacing="1" cellpadding="4" bgcolor="silver">
<tbody>
<tr>
<th bgcolor="#FFFFFF" width="150">
<div align="center">Map</div>
</th>
<th bgcolor="#FFFFFF" width="250">
<div align="center">Run Time(ms)</div>
</th>
<th bgcolor="#FFFFFF" width="150">
<div align="center">Type[order]</div>
</th>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">HashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">744, 739, 736, 741, 741</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[3]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">220, 225, 228, 225, 221</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[2]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">239, 218, 213, 209, 210</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[1]</div>
</td>
</tr>
<tr>
<td rowspan="3" align="center" valign="top" bgcolor="#FFFFFF">
<div align="center">Hashtable</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">694, 726, 699, 685, 686</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[2]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">264, 272, 272, 266, 264</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[4]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">331, 291, 284, 295, 286</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[2]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">LinkedHashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">814, 802, 817, 825, 818</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[4]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">227, 229, 218, 223, 227</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[2]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">481, 466, 472, 475, 473</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[4]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">IdentityHashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">649, 660, 658, 662, 659</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[1]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">181, 186, 188, 191, 182</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[1]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">754, 774, 773, 774, 773</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[5]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">TreeMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">1880, 1879, 1876</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[5]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">1229, 1234, 1270</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[5]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">420, 403, 399, 401, 401</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[3]</div>
</td>
</tr>
</tbody>
</table>
</div>
<p>然后又在实验室的台式电脑上跑了一下测试，基本结果类似。</p>
<p align="center">Java中各个Map的性能测试（台式机，i3/4G）数据表</p>
<div align="center">
<table border="0" cellspacing="1" cellpadding="4" bgcolor="silver">
<tbody>
<tr>
<th bgcolor="#FFFFFF" width="150">
<div align="center">Map</div>
</th>
<th bgcolor="#FFFFFF" width="250">
<div align="center">Run Time(ms)</div>
</th>
<th bgcolor="#FFFFFF" width="150">
<div align="center">Type[order]</div>
</th>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">HashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">422, 423, 438</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[2]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">234, 218, 218</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[2]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">250, 234, 234</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[1]</div>
</td>
</tr>
<tr>
<td rowspan="3" align="center" valign="top" bgcolor="#FFFFFF">
<div align="center">Hashtable</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">407, 422, 406</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[1]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">249, 250, 250</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[4]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">250, 250, 249</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[1]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">LinkedHashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">610, 594, 594</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[4]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">234, 234, 234</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[3]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">265, 280, 280</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[3]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">IdentityHashMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">532, 516, 531</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[3]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">172, 172, 172</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[1]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">327, 328, 312</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[4]</div>
</td>
</tr>
<tr>
<td rowspan="3" valign="top" bgcolor="#FFFFFF">
<div align="center">TreeMap</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">1437, 1421, 1431</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Put[5]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">1185, 1185, 1186</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Get[5]</div>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">
<div align="center">327, 328, 343</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center">Foreach[4]</div>
</td>
</tr>
</tbody>
</table>
</div>
<p>与上一份数据相比，区别如下：</p>
<ul>
<li>HashMap和Hashtable的操作结果类似，但数据基本很接近，差异不大</li>
<li>IdentityHashMap的写入速度比HashMap慢了一些，读的速度依旧最快，foreach虽然仍然很慢但基本和TreeMap一致，没有太夸张</li>
</ul>
<p>从上面数据上可以看出一些有趣的地方，大部分都很好理解，倒是有2处不太理解呢。</p>
<h3>HashMap</h3>
<p>HashMap不愧为精心设计的最常用的Map，读写性能基本上都是最优秀的，即使某项不是最最优秀的也相差无多，综合性能是毫无争议的最高。</p>
<p>这边也谈谈HashMap源码中对Object.hashCode()再次hash的内部函数：static int hash(int h) {}。之前看源码的时候也只是知道它二次hash的目的以及全部二进制抑或和移位的实现方法，代码原理完全没看懂，而且也没有深究二次hash的原因直到在面试天猫的时候被问到了，倒是傻了一下含糊了说了一些猜测的原因，提高hash分布均匀这样的。</p>
<p>这里附上源码中对此函数的注释，不是太好理解。个人理解：这个函数用来避免质量差的hashCode，因为HashMap的hash表是2的整数倍大小的，普通的hashCode在低bit位的冲突会发生的特别多。</p>
<pre>/**
 * Applies a supplemental hash function to a given hashCode, which
 * defends against poor quality hash functions. This is critical
 * because HashMap uses power-of-two length hash tables, that
 * otherwise encounter collisions for hashCodes that do not differ
 * in lower bits.
 */</pre>
<h3>Hashtable</h3>
<p>相信应该没有多少代码会用到Hashtable了，但不得不惊讶于其单论写入（put）性能竟然优于HashMap，虽然快了没多少基本可以忽略，但比较与读和遍历上要慢上一些，这不能不说很神奇，而且从源码层面一直没怎么看出来原因在哪里。因为synchronized修饰包含占用锁的消耗，速度慢一些是好理解的，当然代码上比HashMap要简单一些调用的子函数也少一些但这不足以使得性能会优于HashMap啊，不得其解，求指导~</p>
<h3>LinkedHashMap</h3>
<p>LinkedHashMap从HashMap继承而来，自然速度会慢一些些。主要重写了内部addEntry()方法（主要写操作put时候被调用）来维护插入顺序链表，所以写入速度比HashMap慢是好理解的；默认内部变量accessOrder == false表示不会在get()方法调用时使用LRU策略修改链表，所以默认随机读的性能和HashMap完全一致；至于foreach遍历，HashMap走的是hash table数组，LinkedHashMap走的是链表，指针操作比数组操作慢了一些。</p>
<h3>IdentityHashMap</h3>
<p>IdentityHashMap和以上几个Map使用的冲突策略不同为线性探测法，所有的冲突操作由邻接链表的指针操作转化为数组操作，所以随机读速度比HashMap快了不少，至于写的话大概差不多（两份测试数据不一致），但是foreach遍历却这么慢有点想不通了源代码也没看出所以然来。</p>
<h3>TreeMap</h3>
<p>这个就不用多说了，时间复杂度都不一样的，实现巨复杂的红黑树，当然速度非常慢了，不过它的foreach遍历效率相对而言是比较高的，因为Tree中邻接节点是有连接关系的，和其他Map相差并不多。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>再把上面提到的2个问题列举下：</p>
<ol>
<li>为什么Hashtable单论写入速度比HashMap快？（<span style="color: #0000ff;">不同机器、JVM、JDK版本会导致运行结果差异，所以问题意义不大</span>）</li>
<li>为什么IdentityHashMap的foreach遍历速度却很慢？</li>
</ol>
<div>发博文后，辛苦串叔拿着测试代码和数据在不同的JVM和不同JDK的版本下进行测试，发现结果并不是太一致，所以纠结这快一点慢一点没有太大的意义，可能就是本身Java代码和JVM实现的问题了，所以不再深究啦，大致了解这么一个情况就可以啦。</div>
<h4  class="related_post_title">随便看一看</h4><ul class="related_post"><li>2013-01-15 -- <a target="_blank" href="http://blog.11034.org/2013-01/pack_in_zoj.html" title="背包练习小集合">背包练习小集合</a></li><li>2012-01-16 -- <a target="_blank" href="http://blog.11034.org/2012-01/ipad2.html" title="iPad2入手，变身果粉">iPad2入手，变身果粉</a></li><li>2016-08-30 -- <a target="_blank" href="http://blog.11034.org/2016-08/mysql_linux_ignore_case.html" title="Linux MySQL查询默认情况下不区分大小写">Linux MySQL查询默认情况下不区分大小写</a></li><li>2023-08-24 -- <a target="_blank" href="http://blog.11034.org/2023-08/anlu.html" title="七夕·绍兴安麓">七夕·绍兴安麓</a></li><li>2013-03-13 -- <a target="_blank" href="http://blog.11034.org/2013-03/journey_to_the_west.html" title="大话西游，西游降魔">大话西游，西游降魔</a></li></ul><h4 class="related_post_title">看看 Java , 数据结构和算法 </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2013-05/java_map.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
