Map遍历的四种方法

时间:2023-01-13 19:25:14
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取出值即可。