`
小网客
  • 浏览: 1218000 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HashMap的2中遍历方式比较

 
阅读更多

首先我们准备数据,准备一个map

		Map<String, String> map = new HashMap<String, String>();
		for (int i = 0; i < 10; i++) {
			map.put(i + "", "value" + i);
		}

然后我们采用传说中的key遍历:

步骤:先弄成key set,然后遍历key set 通过key从map中获取value

		Iterator<String> iterator = map.keySet().iterator();
		while (iterator.hasNext()) {
			String key = iterator.next();
			String val = map.get(key);
			System.out.println(key + "->" + val);
		}
		System.out.println("*********************");

然后我们在采用entrySet的方式遍历下:

步骤:先弄成entrySet 然后遍历他,获取key和value

		Set<Entry<String, String>> set = map.entrySet();
		Iterator<Entry<String, String>> s = set.iterator();
		while (s.hasNext()) {
			Entry<String, String> en = s.next();
			String key = en.getKey();
			String val = en.getValue();
			System.out.println(key + "->" + val);
		}

孰优孰劣?

看JDK源码,对比两种访问方式:

首先看KeySet访问方式:

    public Set<K> keySet() {
	if (keySet == null) {
	    keySet = new AbstractSet<K>() {
		public Iterator<K> iterator() {
		    return new Iterator<K>() {
			private Iterator<Entry<K,V>> i = entrySet().iterator();

			public boolean hasNext() {
			    return i.hasNext();
			}

			public K next() {
			    return i.next().getKey();
			}

			public void remove() {
			    i.remove();
			}
                    };
		}

		public int size() {
		    return AbstractMap.this.size();
		}

		public boolean contains(Object k) {
		    return AbstractMap.this.containsKey(k);
		}
	    };
	}
	return keySet;
    }

也就是调用entrySet()从entryset中获取key,也就是说是在entry set的基础上来做的,貌似多次一举

结论:

通过上述代码我们就知道,采用entrySet方式要优于keySet,因为keySet首先要访问entrySet来组建一个keySet,重复工作不言而喻
 

 

9
6
分享到:
评论
14 楼 小网客 2013-11-05  
5开始就有for each风格了,不过我还是偏向iterator,貌似对我来说可读性好 哈
smallplum 写道
tufly 写道
太讨厌 iterator了,JDK5应该都一般装的吧。for each的写法中,keySet应该是只简单的,我只会写
for(Object o:map.keySet()){
System.out.println(o);
System.out.println(map.get(o));
}



可以这样写:
        for(Map.Entry entry : map.entrySet()){
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }

13 楼 smallplum 2013-11-05  
tufly 写道
太讨厌 iterator了,JDK5应该都一般装的吧。for each的写法中,keySet应该是只简单的,我只会写
for(Object o:map.keySet()){
System.out.println(o);
System.out.println(map.get(o));
}



可以这样写:
        for(Map.Entry entry : map.entrySet()){
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }
12 楼 zy19982004 2012-11-21  
ansjsun 写道
zy19982004 写道
keyset时间复杂度O(n*n)
entryset时间复杂度O(n)

keyset时间复杂度O(n*n)????这个是怎么计算出来的???
hash定位是o(1)吧

是我搞错了
11 楼 请输入用户名 2012-11-21  
楼主说的不妥,keySet要慢一丁点主要是会多一次hashCode计算和查找的冲突解决过程,像你说的这里不足为虑。而且当key是字符串的时候,keySet和entrySet花费时间也是相当的,只有hash比较耗时或者命中率很差的情况下,entrySet才会明细优于keySet.
10 楼 zhukewen_java 2012-11-20  
想了很久,为什么标题是说2种而不是说两种?
9 楼 mfkvfn 2012-11-20  
mfkvfn 写道
有什么好争的,运行一遍不就行了。插入10000条记录,然后用两种方式试一下,打印一下用时是多少。

keySet应该要快一丁点。

说错了,keySet要慢一丁点。会多一次hashCode计算和查找的冲突解决过程。
8 楼 mfkvfn 2012-11-20  
有什么好争的,运行一遍不就行了。插入10000条记录,然后用两种方式试一下,打印一下用时是多少。

keySet应该要快一丁点。
7 楼 小网客 2012-11-20  
貌似是不一样 你瞅瞅 你的KeyIterator 的源码是啥 看看他是否通过entrySet()来遍历的?
RyanLu 写道
楼主。。。你这是java.util.HashMap的源代码吗?我的JDK 6版本里面的跟你的不一样。。。
public Set<K> keySet() {
        Set<K> ks = keySet;
        return (ks != null ? ks : (keySet = new KeySet()));
    }

    private final class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return newKeyIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsKey(o);
        }
        public boolean remove(Object o) {
            return HashMap.this.removeEntryForKey(o) != null;
        }
        public void clear() {
            HashMap.this.clear();
        }
    }

HashMap的几种遍历方式都通过内部类实现相应的iterator,这些iterator都是继承内部类Hash Iterator的。效率上来说应该是一样的。
6 楼 RyanLu 2012-11-20  
楼主。。。你这是java.util.HashMap的源代码吗?我的JDK 6版本里面的跟你的不一样。。。
public Set<K> keySet() {
        Set<K> ks = keySet;
        return (ks != null ? ks : (keySet = new KeySet()));
    }

    private final class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return newKeyIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsKey(o);
        }
        public boolean remove(Object o) {
            return HashMap.this.removeEntryForKey(o) != null;
        }
        public void clear() {
            HashMap.this.clear();
        }
    }

HashMap的几种遍历方式都通过内部类实现相应的iterator,这些iterator都是继承内部类Hash Iterator的。效率上来说应该是一样的。
5 楼 ansjsun 2012-11-20  
zy19982004 写道
keyset时间复杂度O(n*n)
entryset时间复杂度O(n)

keyset时间复杂度O(n*n)????这个是怎么计算出来的???
hash定位是o(1)吧
4 楼 zy19982004 2012-11-19  
keyset时间复杂度O(n*n)
entryset时间复杂度O(n)
3 楼 九路车没站牌 2012-11-19  
引用
[img][/img][flash=200,200][/flash]
2 楼 小网客 2012-11-19  
tufly 写道
太讨厌 iterator了,JDK5应该都一般装的吧。for each的写法中,keySet应该是只简单的,我只会写
for(Object o:map.keySet()){
System.out.println(o);
System.out.println(map.get(o));
}

key set方法遍历效率不高
1 楼 tufly 2012-11-19  
太讨厌 iterator了,JDK5应该都一般装的吧。for each的写法中,keySet应该是只简单的,我只会写
for(Object o:map.keySet()){
System.out.println(o);
System.out.println(map.get(o));
}

相关推荐

Global site tag (gtag.js) - Google Analytics