Map的遍歷

一、簡(jiǎn)述

Java 的 map 遍歷有多種方法共耍,如最早的 Iterator,Java5 支持的 foreach,Java8 的 Lambda夷野。HashMap 遍歷從大的方向可分為以下 4 類(lèi):

  1. 迭代器(Iterator)方式遍歷;
  2. for each 方式遍歷荣倾;
  3. Lambda 表達(dá)式遍歷(JDK8+)悯搔;
  4. Streams API 遍歷(JDK8+)。

但每種類(lèi)型下又有不同的實(shí)現(xiàn)方式,因此具體的遍歷方式又可分為:

  1. 使用迭代器(Iterator)EntrySet 的方式進(jìn)行遍歷妒貌。
  2. 使用迭代器(Iterator)KeySet 的方式進(jìn)行遍歷通危。
  3. 使用 for each EntrySet 的方式進(jìn)行遍歷。
  4. 使用 for each KeySet 的方式進(jìn)行遍歷灌曙。
  5. 使用 Lambda 表達(dá)式的方式進(jìn)行遍歷菊碟。
public class TestMap {
  public static Map<String, String> map = new HashMap<String, String>();
    map.put("1", "大象");
    map.put("2", "猴子");
    map.put("3", "老虎");
}

二、entrySet

通過(guò)對(duì) map entrySet 的遍歷在刺,可以同時(shí)拿到 key 和 value逆害。這一般是最常見(jiàn)也是最可取的遍歷方式,在鍵值都需要時(shí)使用蚣驼。一般情況下魄幕,性能上要優(yōu)于方法二。

// entrySet 獲取key and value
public void testEntry() {
  for (Map.Entry<String, String> entry : map.entrySet()) {
     System.out.println(entry.getKey() + ":" + entry.getValue());
  }
}

三颖杏、keySet values

如果只需要 map 的 key 或者 value纯陨,用 map 的 keySet 或 values 方法無(wú)疑是最方便的,而不是用 entrySet留储。

Map<String, String> map = new HashMap<String, String>(); 
//遍歷map中的鍵 
for (String key : map.keySet()) { 
  System.out.println("Key = " + key); 
} 
//遍歷map中的值 
for (String value : map.values()) { 
  System.out.println("Value = " + value); 
}

如果需要同時(shí)獲取 key 和 value翼抠,也可以先獲取 key,然后再通過(guò) map 的 get(key) 獲取 value获讳。作為方法一的替代阴颖,此代碼更簡(jiǎn)潔,但實(shí)際上它相當(dāng)慢且無(wú)效率丐膝。因?yàn)橛面I取值是耗時(shí)的操作(與方法一相比膘盖,在不同的 Map 實(shí)現(xiàn)中該方法慢了20%~200%)。該方法不是最優(yōu)選擇尤误,一般不推薦使用侠畔。

// keySet get(key) 獲取key and value
public void testKeySetAndGetKey() {
  for (String key : map.keySet()) {
    System.out.println(key + ":" + map.get(key));
  }
}

四、Iterator

對(duì)于上面的幾種 foreach 都可以用 Iterator 代替损晤,其實(shí) foreach 在 Java5 中才被支持软棺,foreach 的寫(xiě)法看起來(lái)更簡(jiǎn)潔。
但 Iterator 也有其優(yōu)勢(shì):在用 foreach 遍歷 map 時(shí)尤勋,如果改變其大小喘落,會(huì)報(bào)錯(cuò)。但如果只是刪除元素最冰,可以使用 Iterator 的 remove 方法刪除元素瘦棋,根據(jù) javadoc 的說(shuō)明,如果在 foreach 遍歷中嘗試使用此方法暖哨,結(jié)果是不可預(yù)測(cè)的赌朋。

// Iterator entrySet 獲取key and value
//Iterator:業(yè)務(wù)復(fù)雜的可以用while
public void testIterator() {
  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
  while (it.hasNext()) {
    Map.Entry<String, String> entry = it.next();
    System.out.println(entry.getKey() + ":" + entry.getValue());
    // it.remove(); 刪除元素
  }
}
//Iterator:普通的可以用foreach遍歷
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();it.hasNext();){
    Map.Entry<String,String> entry = it.next(); 
    System.out.println(entry.getKey() + ":" + entry.getValue());    
   //it.remove(); 會(huì)拋java.util.ConcurrentModificationException
}

五、Lambda~流式 map 遍歷(Java8)

Java8 提供了 Lambda 表達(dá)式支持,語(yǔ)法更簡(jiǎn)潔沛慢,可以同時(shí)拿到 key 和 value赡若。不過(guò),經(jīng)測(cè)試性能低于 entrySet团甲,所以更推薦用 entrySet 的方式逾冬。

// Lambda 獲取key and value
//流式一:
public void testLambda() {
   map.forEach((key, value) -> {
      System.out.println(key + ":" + value);
    });
}
//流式二:Streams API 單線程
map.entrySet().stream().forEach(entry->{
 System.out.println("code:"+entry.getKey()+" desc:"+entry.getValue());
});

//流式三:Streams API 多線程
map.entrySet().parallelStream().forEach((entry) -> {
  System.out.println(entry.getKey());
  System.out.println(entry.getValue());
});

六、小結(jié)

  1. 如果只是獲取 key 或 value躺苦,推薦使用 keySet 或 values 方式身腻。
  2. 如果同時(shí)需要 key 和 value 推薦使用 entrySet。
  3. 如果需要在遍歷過(guò)程中刪除元素推薦使用 Iterator匹厘。
  4. 如果需要在遍歷過(guò)程中增加元素霸株,可以新建一個(gè)臨時(shí) map 存放新增的元素,等遍歷完畢集乔,再把臨時(shí) map 放到原來(lái)的 map 中。

七坡椒、Java 中兩個(gè) map 比較

1??用 map 的 keySet() 的迭代器(性能效率較低)

public void compareMap1() {
    Map<String, String> m1 = new HashMap<String, String>();//小
    Map<String, String> m2 = new HashMap<String, String>();//大
    Iterator<String> iter1 = m1.keySet().iterator();
    while (iter1.hasNext()) {
        String m1Key = iter1.next();
        //若兩個(gè)map中相同key對(duì)應(yīng)的value不相等
        if (!m1.get(m1Key).equals(m2.get(m1Key))) {
            //......
        }
    }
}

2??用 map 的 entrySet() 的迭代器(性能效率較高)

public void compareMap2() {
    Map<String, String> m1 = new HashMap<String, String>();
    Map<String, String> m2 = new HashMap<String, String>();
    Iterator<Map.Entry<String, String>> iter1 = m1.entrySet().iterator();
    while (iter1.hasNext()) {
        Map.Entry<String, String> entry1 = iter1.next();
        String m1value = entry1.getValue() == null ? "" : entry1.getValue();
        String m2value = m2.get(entry1.getKey()) == null ? "" : m2.get(entry1.getKey());
        //若兩個(gè)map中相同key對(duì)應(yīng)的value不相等
        if (!m1value.equals(m2value)) {
            //其他操作...
        }
    }
}

3??用 map 的 entrySet() 的增強(qiáng)型 for 循環(huán)(性能效率較高)

public void compareMap3() {
    Map<String, String> m1 = new HashMap<String, String>();
    Map<String, String> m2 = new HashMap<String, String>();
    for (Map.Entry<String, String> entry1 : m1.entrySet()) {
        String m1value = entry1.getValue() == null ? "" : entry1.getValue();
        String m2value = m2.get(entry1.getKey()) == null ? "" : m2.get(entry1.getKey());
        //若兩個(gè)map中相同key對(duì)應(yīng)的value不相等
        if (!m1value.equals(m2value)) {
            //其他操作...
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扰路,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子倔叼,更是在濱河造成了極大的恐慌汗唱,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丈攒,死亡現(xiàn)場(chǎng)離奇詭異哩罪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)巡验,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)际插,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人显设,你說(shuō)我怎么就攤上這事框弛。” “怎么了捕捂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵瑟枫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我指攒,道長(zhǎng)慷妙,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任允悦,我火速辦了婚禮膝擂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己猿挚,他們只是感情好咐旧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著绩蜻,像睡著了一般铣墨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上办绝,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天伊约,我揣著相機(jī)與錄音,去河邊找鬼孕蝉。 笑死屡律,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的降淮。 我是一名探鬼主播超埋,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼佳鳖!你這毒婦竟也來(lái)了霍殴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤系吩,失蹤者是張志新(化名)和其女友劉穎来庭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體穿挨,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡月弛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了科盛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帽衙。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贞绵,靈堂內(nèi)的尸體忽然破棺而出佛寿,到底是詐尸還是另有隱情,我是刑警寧澤但壮,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布冀泻,位于F島的核電站,受9級(jí)特大地震影響蜡饵,放射性物質(zhì)發(fā)生泄漏弹渔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一溯祸、第九天 我趴在偏房一處隱蔽的房頂上張望肢专。 院中可真熱鬧舞肆,春花似錦、人聲如沸博杖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)剃根。三九已至哩盲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狈醉,已是汗流浹背廉油。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苗傅,地道東北人抒线。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渣慕,于是被迫代替她去往敵國(guó)和親嘶炭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容