Java程序员从笨鸟到菜鸟(二十三)HashMap两种遍历方式

方式一:使用entrySet方式

Map<String, Object> map = new HashMap<String, Object>();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry entry = (Map.Entry)iter.next();
    Object key = entry.getKey(); // 获取key值
    Object value = entry.getValue(); // 获取value值
}

也可以使用for循环的形式遍历

Map<String, Object> map = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry: map.entrySet()) {
    entry.getKey();
    entry.getValue();
}

方式二:使用keySet方式

Map<String, Object> map = new HashMap<String, Object>();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
    Object key = iter,next();
    Object value = map.get(key);
}

上面方法也可以用for循环实现

Map<String, Object> map = new HashMap<String, Object>();
for (String key: map.keySet()) {
    map.getKey(key); // 获取value值
}

两种方式效率比较

分析:keySet方式其实是遍历了2次,一次是转为iterator,一次是从HashMap中取出key对应的value,而entrySet方式只遍历了一次,把key和value都放到了entry中。从遍历次数来看,可能会觉得entry方式快一些,但是经过多次测试两者运行时间都差不多
首先从源码分析:
keySet迭代器:

private final class KeyIterator extends HashIterator<K> {
    public K next() {
        return nextEntry().getKey();
    }
}

entrySet迭代器

private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
    public Map.Entry<K,V> next() {
        return nextEntry();
    }
}

从源码中可以看出两者继承父类相同,知识返回值不一样,再看下get方法的源码

public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
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. 如果既需要key也需要value,直接使用entrySet方式遍历HashMap
  2. 如果只是遍历key而无需value的值,可以直接用keySet方式遍历HashMap

大多数情况下是使用entrySet遍历

关于HashMap遍历元素输出顺序问题

HashMap散列图、Hashtable散列表是按“有利于随机查找的散列(hash)的顺序”。并非按输入顺序。遍历时只能全部输出,而没有顺序。甚至可以rehash()重新散列,来获得更利于随机存取的内部顺序.

如果要按加入顺序输出元素,则需要使用LinkedHashmap

原文传送门:http://swiftlet.net/archives/1259

猜你喜欢

转载自blog.csdn.net/u013090299/article/details/80495782