Java HashMap遍历实践

在原始记忆中,Java HashMap遍历,无非是for each或者iterator,但至于在遍历时性能如何,优缺点如何,泛泛而不得知。对于这样的基础问题,对于王二(Java编程6年,幸好我的方向不是编程)我来说,似乎羞于提及,但事实证明,我还必须“积硅步”。

①方法一、iterator迭代keys并搜索values

该种方法是我使用最频繁的,没有之一,详见如下代码:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

addMap(map);

long t1 = System.currentTimeMillis();
Iterator<Integer> keys = map.keySet().iterator();

while (keys.hasNext()) {
    Integer key = keys.next();
    Integer value = map.get(key);

    keys.remove();
}

long t2 = System.currentTimeMillis();
System.out.println("map.keySet().iterator()耗时:" + (t2 - t1));

以前的我看来,该种方法使用起来相当简洁,通过iterator遍历出来keys,然后通过key从map中获取对应的value,似乎也非常接地气。但是,弊端就在于

它更慢更低效,通过key得到value值更耗时(这个方法在所有实现map接口的map中比方法#1慢20%-200%)。如果你安装了FindBugs,它将检测并警告你这是一个低效的迭代。这个方法应该避免

看到这条信息,我是觉得有点唐突,怎么原来最喜欢的一种map遍历方式竟然如此low,简直让人失望。后面我会对花费的性能时间做一个统计,稍候关注。

②方法二、Iterator迭代Entry

这种方法我以前几乎不用,但方法二却有其关键的优点:

  1. 可以通过iterator对map的元素进行删除。方法一同样。
  2. 性能优良。
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
addMap(map);

long t3 = System.currentTimeMillis();
Iterator<Entry<Integer, Integer>> entrys = map.entrySet().iterator();

while (entrys.hasNext()) {
    Entry<Integer, Integer> entry = entrys.next();
    Integer key = entry.getKey();
    Integer value = entry.getValue();

    entrys.remove();
}

long t4 = System.currentTimeMillis();
System.out.println(" map.entrySet().iterator()耗时:" + (t4 - t3));

通过“map.entrySet().iterator()”获得map的entry对象,然后通过getKey,getValue进行key和value值得获取,非常的直白和实用。

③方法三:For-Each迭代keys和values

for each一个局限是不同remove map中的元素,但遍历map还是非常好的。

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
addMap(map);

long t5 = System.currentTimeMillis();
for (Integer key : map.keySet()) {
}

for (Integer value : map.values()) {
}
long t6 = System.currentTimeMillis();
System.out.println("for each map.keySet()、map.values()耗时:" + (t6 - t5));

不过这里,王二有话要说,按照stackoverflow上所说,该种方法要比接下来说的第四种方法“For-Each迭代entries”性能更好(大约快10%),但在我的实践中并非如此,这种方法反而比第四种“For-Each迭代entries”慢得多。

④方法四:For-Each迭代entries

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
addMap(map);

long t7 = System.currentTimeMillis();
for (Entry<Integer, Integer> entry : map.entrySet()) {
    Integer key = entry.getKey();
    Integer value = entry.getValue();
}
long t8 = System.currentTimeMillis();
System.out.println("for each map.entrySet()耗时:" + (t8 - t7));

这种方法就不多做介绍了。

⑤性能时间表

次序 iterator迭代keys并搜索values Iterator迭代Entry For-Each迭代keys和values For-Each迭代entries
1 耗时:37 耗时:32 耗时:39 耗时:13
2 耗时:29 耗时:18 耗时:32 耗时:15
3 耗时:50 耗时:57 耗时:39 耗时:21
4 耗时:47 耗时:31 耗时:39 耗时:14

可以总结如下:

  1. 迭代keys并搜索values 非常低效,排名几乎在倒数第一或第二
  2. For-Each迭代entries 性能最佳,但无法remove
  3. For-Each迭代keys和values并没有比For-Each迭代entries 性能(大约快10%),stackoverflow上的数据也不能全部苟同
  4. Iterator迭代Entry 的方案显然最适合使用,性能优良,且可以remove

参考文章


感谢您阅读【沉默王二的博客】,如果王二的博客给您带来一丝帮助或感动,我(也就是王二)将不甚荣幸。

如果您碰巧喜欢,可以留言或者私信我,这将是我鼓捣更多优秀文章的最强动力。

时间: 2024-10-24 08:10:00

Java HashMap遍历实践的相关文章

Java HashMap 遍历方式探讨

JDK8之前,可以使用keySet或者entrySet来遍历HashMap,JDK8中引入了map.foreach来进行遍历. keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value.而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高.如果是JDK8,使用Map.foreach方法. 1. keySet和entrySet 1.1 基本用法 keySet: Map map=new HashMap();

java 高效的hashmap遍历方法

Hashmap的遍历,key和value通常的方法有两种,及使用entryset或者keyset遍历,下面我们来看下实例. public class TestHashMap { private static void test1(){//效率低 Map<String,String> map = new HashMap<String,String>(); long time1 = System.currentTimeMillis(); for (int i = 0; i < 1

Java 理论与实践: 并发集合类

Java 理论与实践: 并发集合类 DougLea的 util.concurrent 包除了包含许多其他有用的并发构造块之外,还包含了一些主要集合类型 List 和 Map 的高性能的.线程安全的实现.在本月的 Java理论与实践中,BrianGoetz向您展示了用 ConcurrentHashMap 替换 Hashtable 或 synchronizedMap ,将有多少并发程序获益.您可以在本文的 中与作者以及其他读者共享您的想法(您也可以点击文章顶部或者底部的 讨论进入论坛). 在Java

Java HashMap拾遗

Java HashMap拾遗 @author ixenos 零碎知识 尽量返回接口而非实际的类型,如返回List.Set.Map而非ArrayList.HashSet.HashMap,便于更换数据结构,而客户端代码不用改变.这就是针对抽象编程 Map.entrySet 方法返回Map映射的 Set 视图Set<Map.Entry<K,V>>,维护entry键值对 该 set 受Map映射支持,所以对Map映射的更改可在此 set 中反映出来,反之亦然! 如果对该 set 进行迭代的

[翻译]Java HashMap工作原理

大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.HashMap的大量源代码(包括Java 7 和Java 8),来深入理解这个基础的数据结构.在这篇文章中,我会解释java.util.HashMap的实现,描述Java 8实现中添加的新特性,并讨论性能.内存以及使用HashMap时的一些已知问题. 内部存储 Java HashMap类实现了Map<K

Java Map遍历方式的选择

1. 阐述 对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多.理由是:entrySet方法一次拿到所有key和value的集合:而keySet拿到的只是key的集合,针对每个key,都要去Map中额外查找一次value,从而降低了总体效率.那么实际情况如何呢? 为了解遍历性能的真实差距,包括在遍历key+value.遍历key.遍历value等不同场景下的差异,我试着进行了一些对比测试. 2. 对比测试 一开始只进行了简单的测试,但结果却表明k

java 中遍历Map的几种方法

转自: http://blog.csdn.net/wzb56/article/details/7864911 方法分为两类: 一类是基于map的Entry:map.entrySet(); 一类是基于map的key:map.keySet() 而每一类都有两种遍历方式: a.利用迭代器 iterator: b.利用for-each循环: 代码举例如下 package cn.wzb; import java.util.ArrayList; import java.util.HashMap; impor

java中遍历MAP的几种方法

java中遍历MAP的几种方法 Java代码 Map<String,String> map=new HashMap<String,String>();    map.put("username", "qq");    map.put("passWord", "123");    map.put("userID", "1");    map.put("em

HashMap遍历的两种方式,推荐使用entrySet()

转自:HashMap遍历的两种方式,推荐使用entrySet() 第一种: 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(); } 效率