转自:http://swiftlet.net/archives/1259
HashMap的遍历有两种方式,如下所示:
第一种利用entrySet的方式:
1
2
3
4
5
6
7
|
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}
|
上面的方式可以变化为for循环的形式:
1
2
3
4
5
|
Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
}
|
第二种利用keySet的方式:
1
2
3
4
5
6
|
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}
|
上面的方式也可以变化为for循环的形式:
1
2
3
4
|
Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
map.get(key);
}
|
这两种方式那种效率高呢?可以从下面的试验可以看出来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public class Test
{
public static void main(String[] args)
{
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 1000000; i++)
{
map.put(i + "", "hello world");
}
long begin1 = System.currentTimeMillis();
Iterator iterator1 = map.entrySet().iterator();
while (iterator1.hasNext())
{
Map.Entry entry = (Map.Entry) iterator1.next();
Object key1 = entry.getKey();
Object val1 = entry.getValue();
}
long end1 = System.currentTimeMillis();
System.out.println("map.entrySet方式变量花费的时间为:" + (end1 - begin1));
long begin2 = System.currentTimeMillis();
Iterator iterator2 = map.keySet().iterator();
while (iterator2.hasNext())
{
Object key2 = iterator2.next();
Object val2 = map.get(key2);
}
long end2 = System.currentTimeMillis();
System.out.println("map.keySet方式变量花费的时间为:" + (end2 - begin2));
}
}
|
结论:
经过运行多次,我发现两者的运行时间相差不多,而且没有明确显示出那种变量方式更快一些。有的人可能会觉得第一种变量方式会快一些,因为他们觉得:keySet方式其实是遍历了2次,一次是转为iterator,一次就从HashMap中取出key所对应的value,而entry方式只遍历了一次,把key和value都放到了entry中,所以entry方式更快一些。
但是我觉得这种分析的方式比较主观,我们更应该从源码的角度去分析。首先看一下迭代器的源码:
keySet的迭代器:
1
2
3
4
5
|
private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
|
entrySet的迭代器:
1
2
3
4
5
|
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}
|
从上面我们可以看到只是返回值不同而已,父类相同,所以性能相差不多。下面我们再看一下get方法的源码:
1
2
3
4
5
6
|
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
|
从上面的源码发现get的时间复杂度取决于for循环循环次数,即hash算法。所以两种性能差别不大。从上面的分析来看,我们得到最终的结论:
(1)HashMap的循环,如果既需要key也需要value,直接用
1
2
3
4
5
|
Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
}
|
即可,foreach简洁易懂。
(2)如果只是遍历key而无需value的话,可以直接用
1
2
3
4
|
Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
// key process
}
|
HashMap两种遍历方式的深入研究的更多相关文章
-
Java HashMap两种遍历方式
第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Ma ...
-
HashMap的两种遍历方式
HashMap的两种遍历方式 HashMap存储的是键值对:key-value . java将HashMap的键值对作为一个整体对象(java.util.Map.Entry)进行处理,这优化了Hash ...
-
Map的两种遍历方式
********************************************************************************* ****************** ...
-
Map集合的两种遍历方式
Map集合:即 接口Map<K,V> map集合的两种取出方式: 1.Set<k> keyset: 将map中所有的键存入到set集合(即将所有的key值存入到set中) ...
-
HashMap两种遍历数据的方式
HashMap的遍历有两种方式,一种是entrySet的方式,另外一种是keySet的方式. 第一种利用entrySet的方式: Map map = new HashMap(); Iterator i ...
-
Java HashMap 四种遍历方式
HashMap遍历方式包含以下4种: 1.遍历KeySet,再通过Key来getValue. 2.使用entrySet的迭代器. 3.foreach entrySet的方式. 3.foreache v ...
-
python中的字典两种遍历方式
dic = {"k1":"v1", "k2":"v2"} for k in dic: print(dic[K]) for ...
-
关于使用lazytag的线段树两种查询方式的比较研究
说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可. 但是尤其是涉及到区间修改时,lazytag的使用往往能够对于程序的质量起到决定性作用(Ex:一般JSOI ...
-
hashmap两种遍历方法
第一种:使用entryset来进行遍历 Map map=new HashMap(); Iterator iter=map.entrySet().iterator(); while(iter.hasNe ...
随机推荐
-
thinkphp 3.2 单入口 多模块 不能加载index控制器问题
菜鸟一个,大神不用看,很喜欢单入口 多模块的方式,所以想自己设置下,结果看很多教程没看懂,也看到有人在问这个问题,分享下我的项目名称是app,首先运行官方的index.php文件,app目录下生成了三 ...
-
";Principles of Reactive Programming"; 之<;Actors are Distributed>; (1)
week7中的前两节课的标题是”Actors are Distributed",讲了很多Akka Cluster的内容,同时也很难理解. Roland Kuhn并没有讲太多Akka Clus ...
-
overflow:hidden与position:absolute
在做一个下拉框的动画效果中遇到了这个bug,记录一下. 在写下拉框的动画的时候,一般我们的做法都是把下拉框的外盒子设为overflow:hidden,然后设下外层盒子高度,之后通过js慢慢的改变高度从 ...
-
SQL server中如何按照某一字段中的分割符将记录拆成多条
现需要将上结果转换为下结果 上结果查询语句:SELECT TOP 1 id,domain FROM dbo.SimpleTask 下结果转换语句:SELECT a.Id,b.domain FROM ...
-
[Bayes] dchisq: Metropolis-Hastings Algorithm
dchisq gives the density, # 计算出分布下某值处的密度值 pchisq gives the distribution fun ...
-
【kafka学习之三】kafka集群运维
kafka集群维护一.kafka集群启停#启动kafka/home/cluster/kafka211/bin/kafka-server-start.sh -daemon /home/cluster/k ...
-
P2455 [SDOI2006]线性方程组(real gauss)
P2455 [SDOI2006]线性方程组 (upd 2018.11.08: 这才是真正的高斯消元模板) 找到所消未知数(设为x)系数最大的式子,把它提上来 把这个式子的 x 系数约成1 把这个式子用 ...
-
1.1.1 A+B for Input-Output Practice (I)
A+B for Input-Output Practice (I) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
-
Period---hdu1358(循环节 kmp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1358 题意 :求给你个串,前i位子串由某个字符串重复k次得到,求所有的i和k(k>1); 例如: ...
-
转:如何在ArcMap下将栅格图象矢量化的基本步骤 (对影像的校准和配准、栅格图象矢量化)
矢量对象是以矢量的形式,即用方向和大小来综合表示目标的形式描述的对象.例如画面上的一段直线,一个矩形,一个点,一个圆,一个填充的封闭区域--等等. 矢量图形文件就是由这些矢量对象组合而成的描述性文件. ...