獲取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雹洗,遍歷時(shí)不能移除元素穴吹,map大小發(fā)生變化就會(huì)報(bào)錯(cuò)
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啥容,支持在遍歷的時(shí)候刪除元素
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());
// 移除元素不會(huì)報(bào)錯(cuò)
iterator.remove();
}
}
Java 8 以后支持Lambda表達(dá)式击吱,代碼比較簡(jiǎn)潔帥氣
// 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源碼覆醇,其實(shí)也是使用的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);
}
}
簡(jiǎn)單的性能測(cè)試
10萬(wàn)條數(shù)據(jù)測(cè)試結(jié)果鞋仍,單位:毫秒
100萬(wàn)條數(shù)據(jù)測(cè)試結(jié)果落午,單位:毫秒
1000萬(wàn)條數(shù)據(jù)測(cè)試結(jié)果,單位:毫秒
2000萬(wàn)條數(shù)據(jù)測(cè)試結(jié)果,單位:毫秒
只是簡(jiǎn)單的統(tǒng)計(jì)了下遍歷時(shí)間
- 如果需要獲取KV,不建議使用keySet瓷翻,keySet是遍歷兩次才能拿到KV,第一次遍歷取Key对妄,然后根據(jù)Key拿Value
- Lambda形式,代碼寫(xiě)出來(lái)比較漂亮孝常。
- 數(shù)據(jù)量很大的話使用最基礎(chǔ)的EntrySet即可,對(duì)應(yīng)
getKeyAndValue
優(yōu)先保證性能 - 如果需要遍歷時(shí)移除元素喜颁,使用
getKeyAndValueByIterator
著重說(shuō)明下Lambda表達(dá)式,因?yàn)樾绿匦院馁M(fèi)時(shí)間更長(zhǎng)了稿茉,很費(fèi)解,就多測(cè)了幾遍渺蒿,也查了一些資料怠蹂,發(fā)現(xiàn)了一些好東西
Lambda是多線程遍歷的,但是啟動(dòng)的時(shí)候會(huì)比較慢(類似要初始化),所以數(shù)據(jù)量級(jí)上來(lái)之后,Lambda表達(dá)式形式的遍歷優(yōu)勢(shì)就體現(xiàn)出來(lái)了炮温。
比如:從100萬(wàn)的數(shù)據(jù)量到1000萬(wàn)的數(shù)據(jù)量,發(fā)現(xiàn)getKeyAndValue
和getKeyAndValueByIterator
耗費(fèi)時(shí)間接近翻倍,但是Lambda形式耗費(fèi)時(shí)間是縮了一倍(數(shù)據(jù)不精確肯骇,只是大致,但是百萬(wàn)到千萬(wàn)數(shù)據(jù)量的變化上,getKeyAndValueByLambda
耗費(fèi)時(shí)間是很明顯縮短了的)
源碼
public class MyMapTest {
public static Map<String, Object> map = new HashMap<>(8);
public static void main(String[] args) {
// 測(cè)試數(shù)據(jù)姜钳,key和value隨機(jī)生成
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耗費(fèi)時(shí)間:" + calculation(start, end));
start = System.currentTimeMillis();
getValues(map);
end = System.currentTimeMillis();
printf("getValues耗費(fèi)時(shí)間:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValue(map);
end = System.currentTimeMillis();
printf("getKeyAndValue耗費(fèi)時(shí)間:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValueByIterator(map);
end = System.currentTimeMillis();
printf("getKeyAndValueByIterator耗費(fèi)時(shí)間:" + calculation(start, end));
start = System.currentTimeMillis();
getKeyAndValueByLambda(map);
end = System.currentTimeMillis();
printf("getKeyAndValueByLambda耗費(fèi)時(shí)間:" + 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());
;
}
}
// 支持在遍歷的時(shí)候刪除元素
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());
;
// 移除元素不會(huì)報(bào)錯(cuò)
// 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;
}
/**
* 獲取指定長(zhǎng)度的隨機(jī)字符串
* @param length 字符串長(zhǎng)度
* @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();
}
}