獲取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大小發(fā)生變化就會報錯
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表達(dá)式,代碼比較簡潔帥氣
// 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萬條數(shù)據(jù)測試結(jié)果,單位:毫秒

10萬數(shù)據(jù)量
100萬條數(shù)據(jù)測試結(jié)果,單位:毫秒

100萬數(shù)據(jù)量
1000萬條數(shù)據(jù)測試結(jié)果,單位:毫秒

image.png
2000萬條數(shù)據(jù)測試結(jié)果,單位:毫秒

image.png
只是簡單的統(tǒng)計了下遍歷時間
- 如果需要獲取KV,不建議使用keySet,keySet是遍歷兩次才能拿到KV,第一次遍歷取Key,然后根據(jù)Key拿Value
- Lambda形式,代碼寫出來比較漂亮。
- 數(shù)據(jù)量很大的話使用最基礎(chǔ)的EntrySet即可,對應(yīng)
getKeyAndValue優(yōu)先保證性能 - 如果需要遍歷時移除元素,使用
getKeyAndValueByIterator
著重說明下Lambda表達(dá)式,因為新特性耗費時間更長了,很費解,就多測了幾遍,也查了一些資料,發(fā)現(xiàn)了一些好東西
Lambda是多線程遍歷的,但是啟動的時候會比較慢(類似要初始化),所以數(shù)據(jù)量級上來之后,Lambda表達(dá)式形式的遍歷優(yōu)勢就體現(xiàn)出來了。
比如:從100萬的數(shù)據(jù)量到1000萬的數(shù)據(jù)量,發(fā)現(xiàn)getKeyAndValue和getKeyAndValueByIterator耗費時間接近翻倍,但是Lambda形式耗費時間是縮了一倍(數(shù)據(jù)不精確,只是大致,但是百萬到千萬數(shù)據(jù)量的變化上,getKeyAndValueByLambda耗費時間是很明顯縮短了的)
源碼
public class MyMapTest {
public static Map<String, Object> map = new HashMap<>(8);
public static void main(String[] args) {
// 測試數(shù)據(jù),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();
}
}