方式一:使用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算法,所以两者差别不大。
结论:
- 如果既需要key也需要value,直接使用entrySet方式遍历HashMap
- 如果只是遍历key而无需value的值,可以直接用keySet方式遍历HashMap
大多数情况下是使用entrySet遍历
关于HashMap遍历元素输出顺序问题:
HashMap散列图、Hashtable散列表是按“有利于随机查找的散列(hash)的顺序”。并非按输入顺序。遍历时只能全部输出,而没有顺序。甚至可以rehash()重新散列,来获得更利于随机存取的内部顺序.
如果要按加入顺序输出元素,则需要使用LinkedHashmap