Map遍历的四种方法

时间:2021-01-02 19:24:45
package cn.com.collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* @author water
* @version 创建时间:2016年9月12日 下午4:02:42
* 类说明
*/
public class TestMap {

public static void main(String[] args) {
// TODO Auto-generated method stub
Map map = new HashMap(1000);
for(int i=0;i<1000;i++){
map.put(i+"", "str"+i);
}
// 方法一、推荐只用value的时候用
// Map.values()遍历所有的value,不遍历key
for (Object v : map.values()) {
System.out.println("value= " + v);
}
//推荐只用keys的时候用
for(Object key : map.keySet()){
System.out.println("key= "+ key );
}

//方法二:取二次值,先取key再取value,建议只需要用key的时候使用,节省时间、空间
for(Object key : map.keySet()){
System.out.println("key= "+ key + " and value= " + map.get(key));
}

//方法三:取一次值,一次把key和value全部取出
//entrySet使用iterator遍历key和value
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}

// 四、推荐,尤其是容量大时,TreeMap尤其推荐
// entrySet遍历key和value
for (Object obj : map.entrySet()) {
Map.Entry entry = (Map.Entry) obj;
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}

}

}

比较keySet和EntrySet性能

package cn.com.collection;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
* @author gaohuashui
* @version 创建时间:2016年9月12日 下午4:20:18 类说明
*/
public class TestMap2 {

public static void main(String[] args) {
Map map = new HashMap(1000000);
//Map map = new TreeMap();
for (int i = 0; i < 1000000; i++) {
map.put(i + "", "str" + i);
}

// 二次取值
long current = System.currentTimeMillis();
for (Object key : map.keySet()) {
map.get(key);
}
System.out.println("keySet cost time : "+String.valueOf(System.currentTimeMillis() - current));

// entrySet遍历key和value
long current1 = System.currentTimeMillis();
for (Object obj : map.entrySet()) {
Map.Entry entry = (Map.Entry) obj;
entry.getKey();
entry.getValue();
}
System.out.println("entrySet cost time : "+String.valueOf(System.currentTimeMillis() - current1));
}

}
执行以上代码,结果:
keySet cost time : 52
entrySet cost time : 33

由结果我们发现,entrySet 的效率高于keySet。同时遍历key和value时,keySet与entrySet方法的性能差异取决于key的具体情况,如复杂度(复杂对象)、离散度、冲突率等。换言之,取决于HashMap查找value的开销。entrySet一次性取出所有key和value的操作是有性能开销的,当这个损失小于HashMap查找value的开销时,entrySet的性能优势就会体现出来。当key是最简单的数值字符串时,keySet可能反而会更高效,在我的例子中没有测出,总体来说还是推荐使用entrySet。因为当key很简单时,其性能或许会略低于keySet,但却是可控的;而随着key的复杂化,entrySet的优势将会明显体现出来。当然,我们可以根据实际情况进行选择。

当我们将HashMap换成TreeMap时,我们发现EntrySet的效率大大地高出了KeySet。这是由TreeMap的查询效率决定的,也就是说,TreeMap查找value的开销较大,明显高于entrySet一次性取出所有key和value的开销。因此,遍历TreeMap时强烈推荐使用entrySet方法。

当然在使用过程中,如果只需要key时,我们选择keySet,如果只使用Value时,我们使用Values取出值即可。