获取Keys
public static void getKeys(Map<String, Object> map) {
for(String key : map.keySet()) {
printf(key);
}
}
获取values
public static void getValues(Map<String, Object> map) {
for(Object value : map.values()) {
printf(value);
}
}
用entrySet获取key和value,遍历时不能移除元素,map大小发生变化就会报错
public static void getKeyAndValue(Map<String, Object> map) {
for(Map.Entry<String, Object> entry : map.entrySet()) {
printf("key is " + entry.getKey() + " and value is " + entry.getValue());
}
}
Iterator方式获取key和value,支持在遍历的时候删除元素
public static void getKeyAndValueByIterator(Map<String, Object> map) {
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
printf("key is " + entry.getKey() + " and value is " + entry.getValue());
// 移除元素不会报错
iterator.remove();
}
}
Java 8 以后支持Lambda表达式,代码比较简洁帅气
// Java 8 Lambda
public static void getKeyAndValueByLambda(Map<String, Object> map) {
map.forEach((key, value) -> {
printf("key is " + key + " and value is " + value);
});
}
下面是map.forEach源码,其实也是使用的EntrySet
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
简单的性能测试
10万条数据测试结果,单位:毫秒
10万数据量100万条数据测试结果,单位:毫秒
100万数据量1000万条数据测试结果,单位:毫秒
image.png
2000万条数据测试结果,单位:毫秒
image.png
只是简单的统计了下遍历时间
- 如果需要获取KV,不建议使用keySet,keySet是遍历两次才能拿到KV,第一次遍历取Key,然后根据Key拿Value
- Lambda形式,代码写出来比较漂亮。
- 数据量很大的话使用最基础的EntrySet即可,对应
getKeyAndValue
优先保证性能 - 如果需要遍历时移除元素,使用
getKeyAndValueByIterator
着重说明下Lambda表达式,因为新特性耗费时间更长了,很费解,就多测了几遍,也查了一些资料,发现了一些好东西
Lambda是多线程遍历的,但是启动的时候会比较慢(类似要初始化),所以数据量级上来之后,Lambda表达式形式的遍历优势就体现出来了。
比如:从100万的数据量到1000万的数据量,发现getKeyAndValue
和getKeyAndValueByIterator
耗费时间接近翻倍,但是Lambda形式耗费时间是缩了一倍(数据不精确,只是大致,但是百万到千万数据量的变化上,getKeyAndValueByLambda
耗费时间是很明显缩短了的)
源码
public class MyMapTest {
public static Map<String, Object> map = new HashMap<>(8);
public static void main(String[] args) {
// 测试数据,key和value随机生成
for(int i = 0; i < 1000000; i++) {
map.put(getRandomStrBylen(4), getRandomStrBylen(8));
}
long start = System.currentTimeMillis();
getKeys(map);
long end = System.currentTimeMillis();
printf("getKeys耗费时间:" + calculation(start, end));
start = System.currentTimeMillis();
getValues(map);
end = System.currentTimeMillis();
printf("getValues耗费时间:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValue(map);
end = System.currentTimeMillis();
printf("getKeyAndValue耗费时间:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValueByIterator(map);
end = System.currentTimeMillis();
printf("getKeyAndValueByIterator耗费时间:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValueByLambda(map);
end = System.currentTimeMillis();
printf("getKeyAndValueByLambda耗费时间:" + calculation(start, end));
}
public static void getKeys(Map<String, Object> map) {
for(String key : map.keySet()) {
// printf(key);
;
}
}
public static void getValues(Map<String, Object> map) {
for(Object value : map.values()) {
// printf(value);
;
}
}
public static void getKeyAndValue(Map<String, Object> map) {
for(Map.Entry<String, Object> entry : map.entrySet()) {
// printf("key is " + entry.getKey() + " and value is " + entry.getValue());
;
}
}
// 支持在遍历的时候删除元素
public static void getKeyAndValueByIterator(Map<String, Object> map) {
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
// printf("key is " + entry.getKey() + " and value is " + entry.getValue());
;
// 移除元素不会报错
// iterator.remove();
}
}
// Java 8 Lambda
public static void getKeyAndValueByLambda(Map<String, Object> map) {
map.forEach((key, value) -> {
// printf("key is " + key + " and value is " + value);
;
});
}
private static void printf(Object obj) {
System.out.println(String.valueOf(obj));
}
private static long calculation(long start, long end) {
return end - start;
}
/**
* 获取指定长度的随机字符串
* @param length 字符串长度
* @return
*/
private static String getRandomStrBylen(Integer length){
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for(int i = 0;i < length;i++){
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}
网友评论