मैं जावा मानचित्र में प्रत्येक प्रविष्टि पर कुशलता से कैसे पुनरावृत्ति करूं?


3301

अगर मेरे पास Mapजावा में इंटरफ़ेस को लागू करने वाली कोई वस्तु है और मैं उसके भीतर निहित हर जोड़े पर पुनरावृति करना चाहता हूं, तो नक्शे के माध्यम से जाने का सबसे कुशल तरीका क्या है?

क्या तत्वों का क्रम उस विशिष्ट मानचित्र कार्यान्वयन पर निर्भर करेगा जो मेरे पास इंटरफ़ेस के लिए है?


38
जावा 8 में लैंबडा एक्सप्रेशन का उपयोग करते हुए: stackoverflow.com/a/25616206/1503859
नितिन महेश

जवाबों:


5028
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

93
यदि आप ऐसा करते हैं, तो यह काम नहीं करेगा क्योंकि प्रवेश मानचित्र में एक नेस्टेड वर्ग है। java.sun.com/javase/6/docs/api/java/util/Map.html
ScArcher2

266
आप आयात को "आयात java.util.Map.Entry;" के रूप में लिख सकते हैं और यह काम करेगा।
जुजुमा

55
@Pureferret यदि आप इसकी removeविधि को कॉल करने की आवश्यकता है तो केवल एक कारण जो आप एक पुनरावृत्ति का उपयोग करना चाहते हैं । यदि ऐसा है, तो यह अन्य उत्तर आपको दिखाता है कि यह कैसे करना है। अन्यथा, ऊपर दिए गए उत्तर में दिखाया गया बढ़ा हुआ लूप जाने का रास्ता है।
assylias

102
मेरा मानना ​​है कि वर्तमान नामस्थान में आंतरिक वर्ग को आयात करने की तुलना में Map.Entry स्पष्ट है।
योशिय्याहोडर-निष्क्रिय को छोड़कर ..

31
ध्यान दें कि आप उपयोग कर सकते हैं map.values()या map.keySet()यदि आप केवल मान या कुंजी के माध्यम से लूप करना चाहते हैं।
डेगू

1214

अन्य उत्तरों को संक्षेप में प्रस्तुत करने और उन्हें पता करने के लिए कि मुझे क्या पता है, मुझे ऐसा करने के लिए 10 मुख्य तरीके मिले (नीचे देखें)। इसके अलावा, मैंने कुछ प्रदर्शन परीक्षण लिखे (नीचे परिणाम देखें)। उदाहरण के लिए, यदि हम मानचित्र की सभी कुंजियों और मानों का योग खोजना चाहते हैं, तो हम लिख सकते हैं:

  1. का उपयोग करते हुए इटरेटर और Map.Entry

    long i = 0;
    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Integer, Integer> pair = it.next();
        i += pair.getKey() + pair.getValue();
    }
  2. का उपयोग करते हुए foreach और Map.Entry

    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
  3. जावा 8 से forEach का उपयोग करना

    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
  4. KeySet और foreach का उपयोग करना

    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
  5. का उपयोग करते हुए कीसेट और इटरेटर

    long i = 0;
    Iterator<Integer> itr2 = map.keySet().iterator();
    while (itr2.hasNext()) {
        Integer key = itr2.next();
        i += key + map.get(key);
    }
  6. और Map.Entry के लिए उपयोग करना

    long i = 0;
    for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
        Map.Entry<Integer, Integer> entry = entries.next();
        i += entry.getKey() + entry.getValue();
    }
  7. जावा 8 स्ट्रीम एपीआई का उपयोग करना

    final long[] i = {0};
    map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
  8. जावा 8 स्ट्रीम एपीआई समानांतर का उपयोग करना

    final long[] i = {0};
    map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
  9. IterableMap का उपयोग करनाApache Collections

    long i = 0;
    MapIterator<Integer, Integer> it = iterableMap.mapIterator();
    while (it.hasNext()) {
        i += it.next() + it.getValue();
    }
  10. ग्रहण (सीएस) संग्रह के MutableMap का उपयोग करना

    final long[] i = {0};
    mutableMap.forEachKeyValue((key, value) -> {
        i[0] += key + value;
    });

परफॉमेंस परीक्षण (मोड = औसत समय, सिस्टम = विंडोज 8.1 64-बिट, इंटेल i7-4790 3.60 गीगाहर्ट्ज, 16 जीबी)

  1. एक छोटे से नक्शे (100 तत्वों) के लिए, स्कोर 0.308 सबसे अच्छा है

    Benchmark                          Mode  Cnt  Score    Error  Units
    test3_UsingForEachAndJava8         avgt  10   0.308 ±  0.021  µs/op
    test10_UsingEclipseMap             avgt  10   0.309 ±  0.009  µs/op
    test1_UsingWhileAndMapEntry        avgt  10   0.380 ±  0.014  µs/op
    test6_UsingForAndIterator          avgt  10   0.387 ±  0.016  µs/op
    test2_UsingForEachAndMapEntry      avgt  10   0.391 ±  0.023  µs/op
    test7_UsingJava8StreamApi          avgt  10   0.510 ±  0.014  µs/op
    test9_UsingApacheIterableMap       avgt  10   0.524 ±  0.008  µs/op
    test4_UsingKeySetAndForEach        avgt  10   0.816 ±  0.026  µs/op
    test5_UsingKeySetAndIterator       avgt  10   0.863 ±  0.025  µs/op
    test8_UsingJava8StreamApiParallel  avgt  10   5.552 ±  0.185  µs/op
  2. 10000 तत्वों वाले मानचित्र के लिए, स्कोर 37.606 सबसे अच्छा है

    Benchmark                           Mode   Cnt  Score      Error   Units
    test10_UsingEclipseMap              avgt   10    37.606 ±   0.790  µs/op
    test3_UsingForEachAndJava8          avgt   10    50.368 ±   0.887  µs/op
    test6_UsingForAndIterator           avgt   10    50.332 ±   0.507  µs/op
    test2_UsingForEachAndMapEntry       avgt   10    51.406 ±   1.032  µs/op
    test1_UsingWhileAndMapEntry         avgt   10    52.538 ±   2.431  µs/op
    test7_UsingJava8StreamApi           avgt   10    54.464 ±   0.712  µs/op
    test4_UsingKeySetAndForEach         avgt   10    79.016 ±  25.345  µs/op
    test5_UsingKeySetAndIterator        avgt   10    91.105 ±  10.220  µs/op
    test8_UsingJava8StreamApiParallel   avgt   10   112.511 ±   0.365  µs/op
    test9_UsingApacheIterableMap        avgt   10   125.714 ±   1.935  µs/op
  3. 100000 तत्वों वाले मानचित्र के लिए, स्कोर 1184.767 सबसे अच्छा है

    Benchmark                          Mode   Cnt  Score        Error    Units
    test1_UsingWhileAndMapEntry        avgt   10   1184.767 ±   332.968  µs/op
    test10_UsingEclipseMap             avgt   10   1191.735 ±   304.273  µs/op
    test2_UsingForEachAndMapEntry      avgt   10   1205.815 ±   366.043  µs/op
    test6_UsingForAndIterator          avgt   10   1206.873 ±   367.272  µs/op
    test8_UsingJava8StreamApiParallel  avgt   10   1485.895 ±   233.143  µs/op
    test5_UsingKeySetAndIterator       avgt   10   1540.281 ±   357.497  µs/op
    test4_UsingKeySetAndForEach        avgt   10   1593.342 ±   294.417  µs/op
    test3_UsingForEachAndJava8         avgt   10   1666.296 ±   126.443  µs/op
    test7_UsingJava8StreamApi          avgt   10   1706.676 ±   436.867  µs/op
    test9_UsingApacheIterableMap       avgt   10   3289.866 ±  1445.564  µs/op

रेखांकन (मानचित्र आकार के आधार पर प्रदर्शन परीक्षण)

यहां छवि विवरण दर्ज करें

तालिका (मानचित्र आकार के आधार पर इत्र परीक्षण)

          100     600      1100     1600     2100
test10    0.333    1.631    2.752    5.937    8.024
test3     0.309    1.971    4.147    8.147   10.473
test6     0.372    2.190    4.470    8.322   10.531
test1     0.405    2.237    4.616    8.645   10.707
test2     0.376    2.267    4.809    8.403   10.910
test7     0.473    2.448    5.668    9.790   12.125
test9     0.565    2.830    5.952   13.220   16.965
test4     0.808    5.012    8.813   13.939   17.407
test5     0.810    5.104    8.533   14.064   17.422
test8     5.173   12.499   17.351   24.671   30.403

सभी परीक्षण GitHub पर हैं ।


9
@Viacheslav: बहुत अच्छा जवाब। बस यह सोचकर कि कैसे Java8 एप्स को आपके बेंचमार्क में, लैम्ब्डा को कैप्चर करके, बाधा डाला जाता है ... (उदाहरण के long sum = 0; map.forEach( /* accumulate in variable sum*/);लिए sumलंबे समय तक कैप्चर किया जाता है , जो stream.mapToInt(/*whatever*/).sumउदाहरण के लिए कहने की तुलना में धीमा हो सकता है । बेशक आप हमेशा राज्य पर कब्जा करने से बच नहीं सकते हैं, लेकिन यह एक उचित जोड़ हो सकता है। बेंच के लिए।
GPI

17
आपका 8 टेस्ट गलत है। यह तुल्यकालन के बिना विभिन्न थ्रेड्स से एक ही चर का उपयोग करता है। AtomicIntegerसमस्या को हल करने के लिए बदलें ।
15

44
@ZhekaKozlov: माइंडब्लोइंग बड़े त्रुटि मानों को देखें। पर विचार करें की परीक्षा परिणाम यह है कि x±eनिकलता है वहाँ से अंतराल के भीतर परिणाम थे कि x-eकरने के लिए x+eहै, तो सबसे तेजी से परिणाम ( 1184.767±332.968) से लेकर 852के लिए 1518, दूसरा सबसे धीमी (जबकि 1706.676±436.867) के बीच चलती है 1270और 2144, इसलिए परिणाम अभी भी ओवरलैप काफी। अब धीरे परिणाम को देखो, 3289.866±1445.564है, जो बीच अपसारी का मतलब 1844और 4735है और आप जानते हैं कि इन परीक्षण के परिणाम व्यर्थ कर रहे हैं।
होल्गर

8
3 मुख्य कार्यान्वयनों की तुलना करने के बारे में क्या है: हैशपैप, लिंक्डहाशपेज़ और ट्रीपैप?
थियरी

9
# 1 और # 6 बिल्कुल समान हैं। whileबनाम forलूप का उपयोग करना पुनरावृत्ति के लिए एक अलग तकनीक नहीं है। और मुझे आश्चर्य है कि आपके परीक्षणों में उनके बीच इस तरह की भिन्नता है - जो यह बताता है कि परीक्षण बाहरी चीजों से ठीक से अलग नहीं हैं जो आप परीक्षण करने के इच्छुक हैं।
एरिक

293

जावा 8 में आप नए लैम्बडा सुविधाओं का उपयोग करके इसे साफ और तेज कर सकते हैं:

 Map<String,String> map = new HashMap<>();
 map.put("SomeKey", "SomeValue");
 map.forEach( (k,v) -> [do something with key and value] );

 // such as
 map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));

के प्रकार kऔर vसंकलक द्वारा अनुमान लगाया जा जाएगा और उपयोग करने के लिए कोई जरूरत नहीं है Map.Entryअब और।

बहुत आसान!


12
आप नक्शे के साथ क्या करना चाहते हैं, इसके आधार पर, आप map.entrySet().stream() docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
विटाली

1
यह तब काम नहीं करेगा जब आप अपने लैम्बडा एक्सप्रेशन के बाहर घोषित गैर-अंतिम वेरिएबल्स को फॉरएच () से बाहर करना चाहते हैं ...
क्रिस

7
@ क्रिस सही। यदि आप लैम्ब्डा के बाहर से प्रभावी रूप से गैर-अंतिम चर का उपयोग करने का प्रयास करते हैं तो यह काम नहीं करेगा ।
समन्वयक

242

हां, आदेश विशिष्ट मानचित्र कार्यान्वयन पर निर्भर करता है।

@ ScArcher2 में अधिक सुंदर जावा 1.5 सिंटैक्स है । 1.4 में, मैं कुछ ऐसा करूंगा:

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}

41
जबकि-लूप के लिए प्राथमिकता दें। (Iterator प्रविष्टियों के लिए = myMap.entrySet ()) itter (); प्रविष्टियाँ .hasnext ();) {...} इस वाक्यविन्यास के साथ 'प्रविष्टियों' का दायरा केवल लूप के लिए कम हो गया है ।
जय

8
@jpredham आप सही हैं कि forनिर्माण का उपयोग करते हुए for (Entry e : myMap.entrySet)आप संग्रह को संशोधित करने की अनुमति नहीं देंगे, लेकिन @HanuAthena ने जिस उदाहरण का उल्लेख किया है, उसे काम करना चाहिए, क्योंकि यह आपको Iteratorगुंजाइश देता है। (जब तक मैं कुछ याद कर रहा हूँ ...)
pkaeding

1
IntelliJ मुझे त्रुटियाँ दे रहा है Entry thisEntry = (Entry) entries.next();: पहचान नहीं करता है Entry। क्या वह छद्म कोड कुछ और है?
जॉनके

1
@ जॉन्क आयात करने का प्रयास करें java.util.Map.Entry
pkaeding

1
यदि आपके पास पूर्णांक कुंजी और स्ट्रिंग कुंजी है, तो यह समाधान काम नहीं करेगा।

139

एक नक्शे पर पुनरावृत्ति के लिए विशिष्ट कोड है:

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMapविहित मानचित्र कार्यान्वयन है और गारंटी नहीं देता है (या यदि इसे कोई म्यूटेशन ऑपरेशन नहीं किया जाता है, तो यह क्रम नहीं बदलना चाहिए)। यदि उपलब्ध हो तो SortedMapकुंजियों के प्राकृतिक क्रम के आधार पर प्रविष्टियाँ लौटाएँगी ComparatorLinkedHashMapया तो प्रविष्टि प्रविष्टियाँ-आदेश या पहुँच-आदेश पर निर्भर करेगा कि यह कैसे बनाया गया है। EnumMapकुंजियों के प्राकृतिक क्रम में प्रविष्टियाँ लौटाता है।

(अपडेट: मुझे लगता है कि यह अब सच नहीं है। ) ध्यान दें, IdentityHashMap entrySetपुनरावृत्त में वर्तमान में एक अजीबोगरीब कार्यान्वयन है जो Map.Entryप्रत्येक आइटम के लिए एक ही उदाहरण देता है entrySet! हालाँकि, हर बार एक नया इटैलर एडवांस Map.Entryअपडेट किया जाता है।


6
EnumMap के पास इस अजीब व्यवहार के साथ IdentityHashMap
प्रेमराज

1
"LinkedHashMap या तो प्रविष्टियों को [...] एक्सेस-ऑर्डर [...] में लौटा देगा ... ताकि आप उन तत्वों को एक्सेस कर सकें, जो आप उन्हें एक्सेस करते हैं? या तो तनातनी, या कुछ दिलचस्प जो एक विषयांतर का उपयोग कर सकता है। ;-)
जेपी

5
@jpaugh केवल LinkedHashMapगिनती तक सीधे पहुंचता है । उन के माध्यम से iterator, spliterator, entrySet, आदि उपलब्ध बदलाव न करें।
टॉम हॉल्टिन -

1
1. हालांकिअगर ? 2. आखिरी पैराग्राफ ब्रश-अप से लाभान्वित हो सकता है।
पीटर मोर्टेंसन

120

इटरेटर और जेनरिक का उपयोग करने का उदाहरण:

Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Map.Entry<String, String> entry = entries.next();
  String key = entry.getKey();
  String value = entry.getValue();
  // ...
}

14
Iteratorइसके दायरे को सीमित करने के लिए आपको लूप में रखना चाहिए ।
स्टीव कू

@SteveKuo आप "इसका दायरा सीमित करें" से क्या मतलब है?
StudioWorks

12
@StudioWorks for (Iterator<Map.Entry<K, V>> entries = myMap.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<K, V> entry = entries.next(); }। उस निर्माण का उपयोग करके हम entriesलूप के लिए (चर की दृश्यता) के दायरे को सीमित करते हैं ।
कॉमफ्रीक

3
@ComFreek ओह, मैं देख रहा हूं। नहीं पता था कि यह बहुत मायने रखता है।
स्टूडियोवर्क्स

101

यह एक दो भाग प्रश्न है:

मानचित्र की प्रविष्टियों पर पुनरावृति कैसे करें - @ ScArcher2 ने उत्तर दिया है कि पूरी तरह से।

पुनरावृत्ति का क्रम क्या है - यदि आप अभी उपयोग कर रहे हैं Map, तो सख्ती से बोलना, कोई आदेश की गारंटी नहीं है । इसलिए आपको वास्तव में किसी भी कार्यान्वयन द्वारा दिए गए आदेश पर भरोसा नहीं करना चाहिए। हालाँकि, SortedMapइंटरफ़ेस का विस्तार होता है Mapऔर वही प्रदान करता है जो आप खोज रहे हैं - कार्यान्वयन रास्ते को एक सुसंगत क्रम देगा।

NavigableMapएक और उपयोगी विस्तार है - यह SortedMapकुंजी सेट में उनके आदेशित स्थान द्वारा प्रविष्टियों को खोजने के लिए अतिरिक्त तरीकों के साथ है। तो संभवतः यह पहली जगह में पुनरावृत्ति की आवश्यकता को दूर कर सकते हैं - आप विशिष्ट खोजने के लिए सक्षम हो सकता है entryआप उपयोग करने के बाद कर रहे हैं higherEntry, lowerEntry, ceilingEntry, या floorEntryतरीकों। descendingMapविधि भी आप में से एक स्पष्ट विधि देता है ट्रेवर्सल आदेश पीछे


83

मानचित्र पर पुनरावृति करने के कई तरीके हैं।

यहाँ मानचित्र में संग्रहीत एक सामान्य डेटा सेट के लिए उनके प्रदर्शन की तुलना मानचित्र में एक लाख कुंजी मूल्य जोड़े को संग्रहीत करके मानचित्र पर पुनरावृति होगी।

1) entrySet()प्रत्येक लूप के लिए उपयोग करना

for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
    entry.getKey();
    entry.getValue();
}

50 मिली सेकेंड

2) keySet()प्रत्येक लूप के लिए उपयोग करना

for (String key : testMap.keySet()) {
    testMap.get(key);
}

76 मिली सेकेंड

3) का उपयोग entrySet()और पुनरावृत्ति

Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()) {
    Map.Entry<String,Integer> entry = itr1.next();
    entry.getKey();
    entry.getValue();
}

50 मिली सेकेंड

4) का उपयोग keySet()और पुनरावृत्ति

Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
    String key = itr2.next();
    testMap.get(key);
}

75 मिली सेकेंड

मैंने रेफर किया है this link


1
रन बार लेख से लिया जाता है, जिसमें जावा माइक्रोबेनमार्किंग हार्नेस का उपयोग नहीं किया जाता है। इसलिए समय अविश्वसनीय है, जैसा कि कोड, उदाहरण के लिए, जेआईटी कंपाइलर द्वारा पूरी तरह से अनुकूलित किया गया है।
एलेक्स

58

ऐसा करने का सही तरीका स्वीकार किए गए उत्तर का उपयोग करना है क्योंकि यह सबसे कुशल है। मुझे लगता है कि निम्न कोड थोड़ा साफ दिखता है।

for (String key: map.keySet()) {
   System.out.println(key + "/" + map.get(key));
}

15
यह सबसे अच्छा दृष्टिकोण नहीं है, यह प्रविष्टिसेट () का उपयोग करने के लिए बहुत अधिक कुशल है। फाइंडबग्स इस कोड को फ्लैग करेंगे ( फाइंडबग्स सोर्सफोर्गे.नेट देखें / ... )
जेफ ओल्सन

6
@JeffOlson meh, सच में नहीं। मैप लुकअप O (1) है, इसलिए दोनों लूप एक ही तरह से व्यवहार करते हैं। माना जाता है कि माइक्रो बेंचमार्क में यह थोड़ा धीमा होगा लेकिन मैं कभी-कभी ऐसा भी करता हूं क्योंकि मुझे बार-बार टाइप के तर्कों को लिखने से नफरत है। इसके अलावा, यह संभवतः आपके प्रदर्शन की अड़चन नहीं होगी, इसलिए यदि यह कोड को अधिक पठनीय बनाता है तो इसके लिए जाएं।
kritzikratzi

4
विस्तार से अधिक: O(1) = 2*O(1)बहुत बड़ी हे संकेतन की परिभाषा है। आप सही हैं कि यह थोड़ा धीमा चलता है, लेकिन जटिलता के संदर्भ में वे समान हैं।
kritzikratzi

2
टक्कर से या नहीं, मेरा मतलब है कि अगर आप कुछ टकराव से कोई फर्क नहीं पड़ता, तो जाहिर है कि यह एक अलग कहानी है यदि आपके पास केवल टक्कर है। तो तुम बहुत सुंदर हो, लेकिन हाँ, तुम जो कह रहे हो वह सच है।
कृत्तिकरत्ज़ी

2
@ जेफ ओल्सन: "बिग ओ" की जटिलताएं कम नहीं होती हैं, जब केवल एक स्थिर कारक होता है, तो यह टिप्पणी सही है। फिर भी, मेरे लिए यह मायने रखता है कि एक ऑपरेशन में एक घंटे या दो घंटे लगते हैं। अधिक महत्वपूर्ण है, इस बात पर जोर दिया जाना चाहिए कि कारक नहीं है 2 , क्योंकि इससे अधिक पुनरावृत्ति करना entrySet()एक लुकअप को सहन नहीं करता है; यह सभी प्रविष्टियों का सिर्फ एक रैखिक अनुक्रमण है। इसके विपरीत, keySet()कुंजी के प्रति पुनरावृत्‍ति करना और प्रति कुंजी के एक लुकअप को देखना, इसलिए हम यहां शून्य लुकिंग बनाम n लुकअप के बारे में बात कर रहे हैं, जिसका आकार n है Map। तो कारक से परे है 2...
Holger

56

FYI करें, आप भी उपयोग कर सकते हैं map.keySet()और map.values()यदि आप केवल नक्शे के कुंजियों / मूल्यों में रुचि रखते हैं और अन्य नहीं।


42

Java 8 के साथ , आप forEach और lambda अभिव्यक्ति का उपयोग करके मैप को पुनरावृत्त कर सकते हैं,

map.forEach((k, v) -> System.out.println((k + ":" + v)));

40

ग्रहण संग्रह के साथ , आप इंटरफ़ेस forEachKeyValueपर विधि का उपयोग करेंगे MapIterable, जो कि MutableMapऔर ImmutableMapइंटरफेस और उनके कार्यान्वयन द्वारा विरासत में मिला है ।

MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue((key, value) -> result.add(key + value));
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

अनाम आंतरिक वर्ग का उपयोग करते हुए, आप निम्नानुसार कोड लिख सकते हैं:

final MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue(new Procedure2<Integer, String>()
{
    public void value(Integer key, String value)
    {
        result.add(key + value);
    }
});
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);

नोट: मैं एक्लिप्स कलेक्शंस के लिए कमिट हूं।


36

लैम्ब्डा एक्सप्रेशन जावा 8

Java 1.8 (Java 8) में यह अग्रगामी संचालन ( स्ट्रीम ऑपरेशन ) से पूर्व विधि का उपयोग करके बहुत आसान हो गया है जो Iterable इंटरफ़ेस से पुनरावृत्तियों के समान दिखता है ।

बस पेस्ट कॉपी बयान नीचे अपना कोड के लिए और नाम बदलने HashMap से चर एचएम अपने HashMap चर करने के लिए कुंजी-मान पेयर बाहर मुद्रित करने के लिए।

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
 *     Logic to put the Key,Value pair in your HashMap hm
 */

// Print the key value pair in one line.

hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

// Just copy and paste above line to your code.

नीचे नमूना कोड है जिसे मैंने लैम्ब्डा एक्सप्रेशन का उपयोग करने की कोशिश की है । यह सामान बहुत अच्छा है। कोशिश करनी चाहिए।

HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
    Random rand = new Random(47);
    int i = 0;
    while(i < 5) {
        i++;
        int key = rand.nextInt(20);
        int value = rand.nextInt(50);
        System.out.println("Inserting key: " + key + " Value: " + value);
        Integer imap = hm.put(key, value);
        if( imap == null) {
            System.out.println("Inserted");
        } else {
            System.out.println("Replaced with " + imap);
        }               
    }

    hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));

Output:

Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

इसके अलावा एक ही के लिए Spliterator का उपयोग कर सकते हैं ।

Spliterator sit = hm.entrySet().spliterator();

अपडेट करें


ओरेकल डॉक्स के प्रलेखन लिंक शामिल हैं। अधिक लेम्बडा के लिए इस लिंक पर जाएं और एग्रीगेट ऑपरेशंस को अवश्य पढ़ें और स्प्लिटर के लिए इस लिंक पर जाएं


35

सिद्धांत रूप में, सबसे कुशल तरीका मैप के किस कार्यान्वयन पर निर्भर करेगा। ऐसा करने का आधिकारिक तरीका कॉल करना है map.entrySet(), जो एक सेट देता है Map.Entry, जिनमें से प्रत्येक में एक कुंजी और एक मूल्य ( entry.getKey()और entry.getValue()) होता है।

एक idiosyncratic कार्यान्वयन में, यह कुछ अंतर कर सकता है कि आप उपयोग करते हैं map.keySet(), map.entrySet()या कुछ और। लेकिन मैं एक कारण के बारे में सोच भी नहीं सकता कि कोई भी ऐसा क्यों लिखेगा। सबसे अधिक संभावना है कि यह प्रदर्शन के लिए कोई फर्क नहीं पड़ता कि आप क्या करते हैं।

और हां, आदेश कार्यान्वयन पर निर्भर करेगा - साथ ही (संभवतः) सम्मिलन और अन्य हार्ड-टू-कंट्रोल कारकों का क्रम।

[संपादित करें] मैंने valueSet()मूल रूप से लिखा था लेकिन entrySet()वास्तव में इसका जवाब है।


35

जावा 8

हमें forEachएक विधि मिली है जो एक लंबोदर अभिव्यक्ति को स्वीकार करती है । हमें स्ट्रीम एपीआई भी मिले हैं। एक मानचित्र पर विचार करें:

Map<String,String> sample = new HashMap<>();
sample.put("A","Apple");
sample.put("B", "Ball");

कुंजियों पर Iterate:

sample.keySet().forEach((k) -> System.out.println(k));

मूल्यों पर फेरबदल करें:

sample.values().forEach((v) -> System.out.println(v));

प्रविष्टियों के बारे में बताएं (forach और स्ट्रीम का उपयोग करके):

sample.forEach((k,v) -> System.out.println(k + ":" + v)); 
sample.entrySet().stream().forEach((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + ":" + currentValue);
        });

धाराओं के साथ लाभ यह है कि हम जिस मामले में चाहते हैं, उसमें आसानी से समानांतर किया जा सकता है। हमें बस ऊपर के parallelStream()स्थान पर उपयोग करने की आवश्यकता है stream()

forEachOrderedforEachधाराओं के साथ बनाम ? forEachमुठभेड़ आदेश का पालन नहीं करता है (अगर परिभाषित) और स्वाभाविक प्रकृति जहां के रूप में में गैर नियतात्मक है forEachOrderedकरता है। इसलिए forEachगारंटी नहीं देता कि ऑर्डर रखा जाएगा। यह भी जांच इस अधिक के लिए।


32

जावा 8:

आप लैम्ब्डा अभिव्यक्ति का उपयोग कर सकते हैं:

myMap.entrySet().stream().forEach((entry) -> {
    Object currentKey = entry.getKey();
    Object currentValue = entry.getValue();
});

अधिक जानकारी के लिए, इसका अनुसरण करें


@injecteer: मेमने के भावों का मकसद
मानते हैं

9
यदि आपको सिर्फ एक नक्शे पर पुनरावृति करना है तो आपको एक स्ट्रीम की आवश्यकता नहीं है। myMap.forEach( (currentKey,currentValue) -> /* action */ );अधिक संक्षिप्त है।
होल्गर

28

जावा 1.4 के साथ यह कोशिश करें:

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

  Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() + "/" + entry.getValue());

  //...
}

25

मानचित्र में एक से अधिक पर keys/ valuesऔर / या / और both (e.g., entrySet) किसी की दिलचस्पी in_ पर निर्भर हो सकता है:

  1. keys -> keySet()मानचित्र के माध्यम से सूचना दें :

    Map<String, Object> map = ...;
    
    for (String key : map.keySet()) {
        //your Business logic...
    }
  2. values -> values()मानचित्र के माध्यम से सूचना दें :

    for (Object value : map.values()) {
        //your Business logic...
    }
  3. both -> entrySet()मानचित्र के माध्यम से सूचना दें :

    for (Map.Entry<String, Object> entry : map.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        //your Business logic...
    }

_Moverover, HashMap के माध्यम से Iterate करने के लिए 3 अंतर तरीके हैं। वे नीचे हैं__

//1.
for (Map.Entry entry : hm.entrySet()) {
    System.out.print("key,val: ");
    System.out.println(entry.getKey() + "," + entry.getValue());
}

//2.
Iterator iter = hm.keySet().iterator();
while(iter.hasNext()) {
    Integer key = (Integer)iter.next();
    String val = (String)hm.get(key);
    System.out.println("key,val: " + key + "," + val);
}

//3.
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry entry = (Map.Entry) it.next();
    Integer key = (Integer)entry.getKey();
    String val = (String)entry.getValue();
    System.out.println("key,val: " + key + "," + val);
}

24

जावा 8 के साथ सबसे कॉम्पैक्ट:

map.entrySet().forEach(System.out::println);

21

यदि आपके पास एक जेनेरिक अप्रकाशित मानचित्र है जिसका आप उपयोग कर सकते हैं:

Map map = new HashMap();
for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

20
public class abcd{
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Integer key:testMap.keySet()) {
            String value=testMap.get(key);
            System.out.println(value);
        }
    }
}

या

public class abcd {
    public static void main(String[] args)
    {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Entry<Integer, String> entry : testMap.entrySet()) {
            Integer key=entry.getKey();
            String value=entry.getValue();
        }
    }
}

17

अगर मेरे पास जावा में मैप इंटरफ़ेस को लागू करने वाली कोई वस्तु है और मैं चाहता हूं कि इसमें निहित प्रत्येक जोड़ी पर पुनरावृति हो, तो नक्शे के माध्यम से जाने का सबसे कुशल तरीका क्या है?

यदि कुंजियों को लूप करने की दक्षता आपके ऐप के लिए प्राथमिकता है, तो एक Mapकार्यान्वयन चुनें जो आपके वांछित क्रम में कुंजियों को बनाए रखता है।

क्या तत्वों का क्रम उस विशिष्ट मानचित्र कार्यान्वयन पर निर्भर करेगा जो मेरे पास इंटरफ़ेस के लिए है?

हाँ बिल्कुल।

  • कुछ Mapकार्यान्वयन एक निश्चित पुनरावृत्ति क्रम का वादा करते हैं, अन्य नहीं करते हैं।
  • Mapकुंजी-मूल्य जोड़े के अलग-अलग क्रम को बनाए रखने के विभिन्न कार्यान्वयन ।

इस तालिका को देखें मैंने Mapजावा 11 के साथ बंडल किए गए विभिन्न कार्यान्वयन को संक्षेप में बनाया है । विशेष रूप से, पुनरावृत्ति क्रम कॉलम पर ध्यान दें । ज़ूम करने के लिए / टैप करें क्लिक करें।

जावा 11 में मानचित्र कार्यान्वयन की तालिका, उनकी विशेषताओं की तुलना करते हुए

आप देख सकते हैं कि वहाँ हैं Map एक आदेश का पालन करने वाले चार कार्यान्वयन :

  • TreeMap
  • ConcurrentSkipListMap
  • LinkedHashMap
  • EnumMap

NavigableMap इंटरफेस

उनमें से दो NavigableMapइंटरफ़ेस को लागू करते हैं : TreeMapऔर ConcurrentSkipListMap

पुराने SortedMapइंटरफ़ेस को नए NavigableMapइंटरफ़ेस द्वारा प्रभावी रूप से दबाया गया है। लेकिन आप केवल पुराने इंटरफ़ेस को लागू करने वाले तृतीय-पक्ष कार्यान्वयन पा सकते हैं।

स्वाभाविक विधान

अगर आप ए Map कि कुंजी के "प्राकृतिक क्रम" द्वारा उसके जोड़े को व्यवस्थित रखा जाए, तो उपयोग करें TreeMapया ConcurrentSkipListMap। "प्राकृतिक क्रम" शब्द का अर्थ है, कुंजियों का वर्ग ComparablecompareToविधि द्वारा लौटाया गया मान छँटाई में तुलना के लिए उपयोग किया जाता है।

सीमा - शुल्क आदेश

यदि आप अपनी कुंजियों के लिए एक क्रमबद्ध क्रम बनाए रखने में उपयोग की जाने वाली कस्टम छँटाई दिनचर्या निर्दिष्ट करना चाहते हैं, तो अपनी कुंजियों Comparatorके वर्ग के लिए उपयुक्त कार्यान्वयन पास करें। TreeMapया तो उपयोग करें या ConcurrentSkipListMap, अपने पासिंग Comparator

मूल सम्मिलन क्रम

यदि आप चाहते हैं कि आपके नक्शे के जोड़े उनके मूल क्रम में रखे जाएं जिसमें आपने उन्हें मानचित्र में सम्मिलित किया है, तो उपयोग करें LinkedHashMap

Enum- परिभाषा क्रम

यदि आप किसी एंम का उपयोग कर रहे हैं जैसे कि DayOfWeekया Monthआपकी कुंजी के रूप में, EnumMapकक्षा का उपयोग करें । न केवल यह वर्ग है अत्यधिक बहुत कम स्मृति का उपयोग करने के लिए अनुकूलित और बहुत तेजी से चलाने के लिए, यह enum द्वारा परिभाषित क्रम में अपने जोड़े रखता है। उदाहरण DayOfWeekके लिए, पहले की कुंजी को DayOfWeek.MONDAYपुनरावृत्त होने पर पाया जाएगा और DayOfWeek.SUNDAYअंतिम की कुंजी अंतिम होगी।

अन्य बातें

चुनने में Mapकार्यान्वयन , इस पर भी विचार करें:

  • NULLs। कुछ कार्यान्वयनों ने एक NULL को कुंजी और / या मान के रूप में मना / स्वीकार किया है।
  • संगामिति। यदि आप थ्रेड्स में मानचित्र में हेरफेर कर रहे हैं, तो आपको एक कार्यान्वयन का उपयोग करना होगा जो समरूपता का समर्थन करता है। या के साथ नक्शा लपेटोCollections::synchronizedMap (कम बेहतर) के ।

ये दोनों विचार ऊपर की ग्राफिक तालिका में शामिल हैं।


एक उत्तर पर देर से टिप्पणी कि पार्टी के लिए देर हो चुकी है (लेकिन बहुत जानकारीपूर्ण)। उल्लेख करने के लिए मेरी ओर से +1 EnumMap, चूंकि यह पहली बार मैंने सुना है। संभवत: ऐसे कई मामले हैं जहां यह काम आ सकता है।
user991710

15

आदेश हमेशा विशिष्ट मानचित्र कार्यान्वयन पर निर्भर करेगा। जावा 8 का उपयोग करके आप इनमें से किसी का भी उपयोग कर सकते हैं:

map.forEach((k,v) -> { System.out.println(k + ":" + v); });

या:

map.entrySet().forEach((e) -> {
            System.out.println(e.getKey() + " : " + e.getValue());
        });

परिणाम समान (समान क्रम) होगा। एंट्रीसेट मैप द्वारा समर्थित है तो आपको वही ऑर्डर मिल रहा है। दूसरा एक काम है क्योंकि यह आपको लैम्ब्डा का उपयोग करने की अनुमति देता है, उदाहरण के लिए यदि आप केवल केवल पूर्णांक वस्तुओं को प्रिंट करना चाहते हैं जो आपके पास हैं:

map.entrySet()
    .stream()
    .filter(e-> e.getValue() > 5)
    .forEach(System.out::println);

नीचे दिए गए कोड LinkedHashMap और सामान्य HashMap (उदाहरण) के माध्यम से पुनरावृति दिखाता है। आपको क्रम में अंतर दिखाई देगा:

public class HMIteration {


    public static void main(String[] args) {
        Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
        Map<Object, Object> hashMap = new HashMap<>();

        for (int i=10; i>=0; i--) {
            linkedHashMap.put(i, i);
            hashMap.put(i, i);
        }

        System.out.println("LinkedHashMap (1): ");
        linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nLinkedHashMap (2): ");

        linkedHashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });


        System.out.println("\n\nHashMap (1): ");
        hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });

        System.out.println("\nHashMap (2): ");

        hashMap.entrySet().forEach((e) -> {
            System.out.print(e.getKey() + " : " + e.getValue() + ", ");
        });
    }
}

लिंक्डहाशपैप (1):

10 (# = 10): 10, 9 (# = 9): 9, 8 (# = 8): 8, 7 (# = 7): 7, 6 (# = 6): 6, 5 (# = 5) ): 5, 4 (# = 4): 4, 3 (# = 3): 3, 2 (# = 2): 2, 1 (# = 1): 1, 0 (# = 0): 0

लिंक्डहाशपैप (2):

10: 10, 9: 9, 8: 8, 7: 7, 6: 6, 5: 5, 4: 4, 3: 3, 2: 2, 1: 1, 0: 0

हशपप (1):

0 (#: 0): 0, 1 (#: 1): 1, 2 (#: 2): 2, 3 (#: 3): 3, 4 (#: 4): 4, 5 (#: 5) ): 5, 6 (#: 6): 6, 7 (#: 7): 7, 8 (#: 8): 8, 9 (#: 9): 9, 10 (#: 10): 10

हशपप (2):

0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10,


14
    Iterator iterator = map.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry element = (Map.Entry)it.next();
        LOGGER.debug("Key: " + element.getKey());
        LOGGER.debug("value: " + element.getValue());    
    }


13

आप इसे जेनरिक का उपयोग करके कर सकते हैं:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

12

मानचित्र पर एक प्रभावी पुनरावृत्ति समाधान जावा 5 के माध्यम से जावा 5 से प्रत्येक के लिए एक '' है 7. यहाँ यह है:

for (String key : phnMap.keySet()) {
    System.out.println("Key: " + key + " Value: " + phnMap.get(key));
}

Java 8 से आप एक लैम्बडा एक्सप्रेशन का उपयोग मैप पर पुन: व्यवस्थित करने के लिए कर सकते हैं। यह एक बढ़ाया 'फॉर' है

phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));

यदि आप लंबोदर के लिए एक सशर्त लिखना चाहते हैं तो आप इसे इस तरह लिख सकते हैं:

phnMap.forEach((k,v)->{
    System.out.println("Key: " + k + " Value: " + v);
    if("abc".equals(k)){
        System.out.println("Hello abc");
    }
});

10
           //Functional Oprations
            Map<String, String> mapString = new HashMap<>();
            mapString.entrySet().stream().map((entry) -> {
                String mapKey = entry.getKey();
                return entry;
            }).forEach((entry) -> {
                String mapValue = entry.getValue();
            });

            //Intrator
            Map<String, String> mapString = new HashMap<>();
            for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {
                Map.Entry<String, String> entry = it.next();
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();
            }

            //Simple for loop
            Map<String, String> mapString = new HashMap<>();
            for (Map.Entry<String, String> entry : mapString.entrySet()) {
                String mapKey = entry.getKey();
                String mapValue = entry.getValue();

            }

10

ऐसा करने के कई तरीके हैं। नीचे कुछ सरल कदम दिए गए हैं:

मान लीजिए कि आपके पास एक मानचित्र है जैसे:

Map<String, Integer> m = new HashMap<String, Integer>();

फिर आप मानचित्र तत्वों पर पुनरावृति करने के लिए नीचे जैसा कुछ कर सकते हैं।

// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
    Entry<String, Integer> pair = me.next();
    System.out.println(pair.getKey() + ":" + pair.getValue());
}

// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
    System.out.println(me.getKey() + " : " + me.getValue());
}

// *********** Using keySet *****************************
for(String s : m.keySet()){
    System.out.println(s + " : " + m.get(s));
}

// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
    String key = me.next();
    System.out.println(key + " : " + m.get(key));
}

9
package com.test;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Test {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("ram", "ayodhya");
        map.put("krishan", "mathura");
        map.put("shiv", "kailash");

        System.out.println("********* Keys *********");
        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key);
        }

        System.out.println("********* Values *********");
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }

        System.out.println("***** Keys and Values (Using for each loop) *****");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println("Key: " + entry.getKey() + "\t Value: "
                    + entry.getValue());
        }

        System.out.println("***** Keys and Values (Using while loop) *****");
        Iterator<Entry<String, String>> entries = map.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry<String, String>) entries
                    .next();
            System.out.println("Key: " + entry.getKey() + "\t Value: "
                    + entry.getValue());
        }

        System.out
                .println("** Keys and Values (Using java 8 using lambdas )***");
        map.forEach((k, v) -> System.out
                .println("Key: " + k + "\t value: " + v));
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.