java遍历map方法
2015-06-01 10:05
453 查看
java 代码:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
// 第一种:通过Map.keySet遍历key和value
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= " + key + " and value= " + map.get(key));
}
// 第二种:通过Map.entrySet使用iterator遍历key和value
System.out.println("通过Map.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());
}
// 第三种:通过Map.entrySet遍历key和value
System.out.println("通过Map.entrySet遍历key和value:");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= "
+ entry.getValue());
}
// 第四种:通过Map.values()遍历所有的value,但是不能遍历键key
System.out.println("通过Map.values()遍历所有的value:");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
结果:
通过Map.keySet遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.entrySet使用iterator遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.entrySet遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.values()遍历所有的value:
value= 3
value= 2
value= 1
这四种方法都可以遍历map:
第一种是目前许多人最喜欢的一种方式,因为代码最少,看起来最简单,通过遍历keySet,再将key所对应的value查询出来,这里有一个二次取值的过程,所以并不推荐;
第二种和第三种原理是相同的,都是通过遍历Map.Entry的方式,将Entry中的key和value打印出来,第三种是比较推荐写法,因为采用jdk1.5后的遍历形式,代码看起来比较整洁;
第四种比较少用,因为我们大多数时候都是同时需要key和value的
综上所述,如果map里面内容比较少,其实采用哪种方式都可以,第一种和第三种相对简洁一些;但是一旦容量非常大时,更推荐采用第三种方式,相比于第一种将极大地节省性能。
修改一下代码,对执行时间执行一下测试
Java代码
import java.util.HashMap;
import java.util.Map;
public class MapTest {
static long MAX_LONG = 1000000L;
static int TIMES = 10;
static Map<String, String> map1 = new HashMap<String, String>();
static Map<String, String> map2 = new HashMap<String, String>();
static {
for (long i = 0; i < MAX_LONG; i++) {
map1.put("1" + i, "abc" + i);
map2.put("2" + i, "def" + i);
}
}
public static void main(String[] args) {
String valueStr = "";
String keyStr = "";
long start, end;
double totalMs;
totalMs = 0;
for (int i = 0; i < TIMES; i++) {
// 通过Map.keySet遍历key和value
start = System.currentTimeMillis();
for (String key : map1.keySet()) {
keyStr = key;
valueStr = map1.get(key);
}
end = System.currentTimeMillis();
System.out.println("通过Map.keySet遍历key和value耗时 " + (end - start)
+ " ms ");
totalMs += (end - start);
}
System.out.println("Times : " + TIMES + ", totalMs : " + totalMs
+ "ms, average :" + totalMs / TIMES + "ms");
}
}
以下是测试结果:
Java代码
通过Map.keySet遍历key和value耗时 186 ms
通过Map.keySet遍历key和value耗时 189 ms
通过Map.keySet遍历key和value耗时 87 ms
通过Map.keySet遍历key和value耗时 89 ms
通过Map.keySet遍历key和value耗时 84 ms
通过Map.keySet遍历key和value耗时 92 ms
通过Map.keySet遍历key和value耗时 85 ms
通过Map.keySet遍历key和value耗时 94 ms
通过Map.keySet遍历key和value耗时 89 ms
通过Map.keySet遍历key和value耗时 91 ms
Times : 10, totalMs : 1086.0ms, average :108.6ms
通过Map.entrySet遍历key和value耗时 112 ms
通过Map.entrySet遍历key和value耗时 98 ms
通过Map.entrySet遍历key和value耗时 71 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 64 ms
通过Map.entrySet遍历key和value耗时 64 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
Times : 10, totalMs : 734.0ms, average :73.4ms 可以看出,百万级别的量时,使用keySet和entrySet遍历,执行时间大概为1.5:1,这并不是最主要的差异。真正的差异还是必须看代码
Java代码
map.get(key))
时执行的hash操作
Java代码
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
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.equals(k)))
return e.value;
}
return null;
}
计算hashCode是CPU密集运算,非常耗费CPU资源,如果对一个比较大的map进行遍历,会出现CPU迅速飚高的现象,直接影响机器的响应速度,在多线程的情况下,简直就是一场灾难,而采用entrySet来进行遍历,则无此问题,对这个有兴趣的同学,可以使用自己的机器试一试。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
// 第一种:通过Map.keySet遍历key和value
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= " + key + " and value= " + map.get(key));
}
// 第二种:通过Map.entrySet使用iterator遍历key和value
System.out.println("通过Map.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());
}
// 第三种:通过Map.entrySet遍历key和value
System.out.println("通过Map.entrySet遍历key和value:");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= "
+ entry.getValue());
}
// 第四种:通过Map.values()遍历所有的value,但是不能遍历键key
System.out.println("通过Map.values()遍历所有的value:");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
结果:
通过Map.keySet遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.entrySet使用iterator遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.entrySet遍历key和value:
key= 3 and value= 3
key= 2 and value= 2
key= 1 and value= 1
通过Map.values()遍历所有的value:
value= 3
value= 2
value= 1
这四种方法都可以遍历map:
第一种是目前许多人最喜欢的一种方式,因为代码最少,看起来最简单,通过遍历keySet,再将key所对应的value查询出来,这里有一个二次取值的过程,所以并不推荐;
第二种和第三种原理是相同的,都是通过遍历Map.Entry的方式,将Entry中的key和value打印出来,第三种是比较推荐写法,因为采用jdk1.5后的遍历形式,代码看起来比较整洁;
第四种比较少用,因为我们大多数时候都是同时需要key和value的
综上所述,如果map里面内容比较少,其实采用哪种方式都可以,第一种和第三种相对简洁一些;但是一旦容量非常大时,更推荐采用第三种方式,相比于第一种将极大地节省性能。
修改一下代码,对执行时间执行一下测试
Java代码
import java.util.HashMap;
import java.util.Map;
public class MapTest {
static long MAX_LONG = 1000000L;
static int TIMES = 10;
static Map<String, String> map1 = new HashMap<String, String>();
static Map<String, String> map2 = new HashMap<String, String>();
static {
for (long i = 0; i < MAX_LONG; i++) {
map1.put("1" + i, "abc" + i);
map2.put("2" + i, "def" + i);
}
}
public static void main(String[] args) {
String valueStr = "";
String keyStr = "";
long start, end;
double totalMs;
totalMs = 0;
for (int i = 0; i < TIMES; i++) {
// 通过Map.keySet遍历key和value
start = System.currentTimeMillis();
for (String key : map1.keySet()) {
keyStr = key;
valueStr = map1.get(key);
}
end = System.currentTimeMillis();
System.out.println("通过Map.keySet遍历key和value耗时 " + (end - start)
+ " ms ");
totalMs += (end - start);
}
System.out.println("Times : " + TIMES + ", totalMs : " + totalMs
+ "ms, average :" + totalMs / TIMES + "ms");
}
}
以下是测试结果:
Java代码
通过Map.keySet遍历key和value耗时 186 ms
通过Map.keySet遍历key和value耗时 189 ms
通过Map.keySet遍历key和value耗时 87 ms
通过Map.keySet遍历key和value耗时 89 ms
通过Map.keySet遍历key和value耗时 84 ms
通过Map.keySet遍历key和value耗时 92 ms
通过Map.keySet遍历key和value耗时 85 ms
通过Map.keySet遍历key和value耗时 94 ms
通过Map.keySet遍历key和value耗时 89 ms
通过Map.keySet遍历key和value耗时 91 ms
Times : 10, totalMs : 1086.0ms, average :108.6ms
通过Map.entrySet遍历key和value耗时 112 ms
通过Map.entrySet遍历key和value耗时 98 ms
通过Map.entrySet遍历key和value耗时 71 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 64 ms
通过Map.entrySet遍历key和value耗时 64 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
通过Map.entrySet遍历key和value耗时 65 ms
Times : 10, totalMs : 734.0ms, average :73.4ms 可以看出,百万级别的量时,使用keySet和entrySet遍历,执行时间大概为1.5:1,这并不是最主要的差异。真正的差异还是必须看代码
Java代码
map.get(key))
时执行的hash操作
Java代码
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
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.equals(k)))
return e.value;
}
return null;
}
计算hashCode是CPU密集运算,非常耗费CPU资源,如果对一个比较大的map进行遍历,会出现CPU迅速飚高的现象,直接影响机器的响应速度,在多线程的情况下,简直就是一场灾难,而采用entrySet来进行遍历,则无此问题,对这个有兴趣的同学,可以使用自己的机器试一试。
相关文章推荐
- java复习(六)
- ArrayList线程不安全分析
- Java多线程学习笔记
- Struts2初识
- 使用Spring3.0的AOP结合log4j实现接口方法执行时间记录
- 基于Spring AOP实现对外接口的耗时监控
- Spring详细教程
- 如何用Spring 3.1的Environment和Profile简化工作
- Java数组不能通过toString方法转为字符串
- SpringAop在项目中的一些巧妙使用(一)---方法执行时间记录
- JAVA递归生成tree树
- SpringMVC 文件上传配置,多文件上传,使用的MultipartFile
- spring aop 实现方法执行时间监控
- Maven Java EE Configuration Problem问题
- JAVA中接口存在的意义
- java获取中文配置文件
- struts2标签中<s:textfield>中label不显示
- Java NIO 06=====Selector
- java Swing实现右键复制粘贴
- RabbitMQ 入门指南(Java)