सवाल एक हैश मैप के माध्यम से Iterate [डुप्लिकेट]


संभावित डुप्लिकेट: 
'मानचित्र' में प्रत्येक प्रविष्टि को कुशलता से कैसे सक्रिय किया जाए?

वस्तुओं में पुन: प्रयास करने का सबसे अच्छा तरीका क्या है HashMap?


2833
2018-06-30 23:24


मूल


मुझे चाबियाँ और मान प्राप्त करने और उन्हें एक बहुआयामी सरणी में जोड़ने की आवश्यकता है - burntsugar
प्रश्न के मुकाबले इसका उच्च स्कोर कैसे है? - immibis
लैम्ब्डा अभिव्यक्ति का उपयोग कर जावा 8 में: stackoverflow.com/a/25616206/1503859 - Nitin Mahesh
@immibis शायद इसलिए कि बहुत से लोग सहजता से अन्य मानचित्र कार्यान्वयन पर विचार किए बिना हैशमैप्स का उपयोग करते हैं। फिर जब वे अनिवार्य रूप से अपने हैश मैप पर फिर से प्रयास करने की कोशिश कर रहे हैं तो वे Google में "हैश मैप के माध्यम से इटरेट" पंच करते हैं, जिससे उन्हें सीधे यहां ले जाता है। - Dean Wild


जवाब:


के माध्यम से Iterate entrySet() इस तरह:

public static void printMap(Map mp) {
    Iterator it = mp.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry)it.next();
        System.out.println(pair.getKey() + " = " + pair.getValue());
        it.remove(); // avoids a ConcurrentModificationException
    }
}

पर और अधिक पढ़ें Map


2842
2018-06-30 23:27



हालांकि पुरानी शैली, यह नीचे दिए गए उत्तरों में नई foreach शैली पर ConcurrentModificationExceptions से बचने में मदद करेगा। उदाहरण के लिए आप पृथक इटरेटर के माध्यम से हटा सकते हैं। - Benjamin Wootton
@ karim79 आप निम्न तरीके से क्या सोचते हैं: Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } - fresh_dev
'it.remove () को कॉल करके; 'यदि नक्शा एक वर्ग चर था तो आप मानचित्र को खाली कर रहे हैं, इसे पुन: प्रयोज्य नहीं कर रहे हैं। क्या आपके पास इसका कोई समाधान है? - vimukthi
@vimukthi आप इसका समाधान क्या मतलब है? बस हटा दें it.remove(); लाइन। - Danny
के लिए (Map.Entry<String, Object> cursor : map.entrySet()) {...} वाक्यविन्यास बहुत बेहतर है। - Chad Okere


यदि आप केवल चाबियों में रुचि रखते हैं, तो आप इसके माध्यम से फिर से शुरू कर सकते हैं keySet() मानचित्र का:

Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

यदि आपको केवल मूल्यों की आवश्यकता है, तो उपयोग करें values():

for (Object value : map.values()) {
    // ...
}

अंत में, यदि आप दोनों कुंजी और मूल्य चाहते हैं, तो उपयोग करें entrySet():

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

एक चेतावनी: यदि आप मध्य-पुनरावृत्ति आइटम को हटाना चाहते हैं, तो आपको एक इटरेटर के माध्यम से ऐसा करने की आवश्यकता होगी (देखें करीम 7 9 का जवाब)। हालांकि, आइटम मान बदलना ठीक है (देखें Map.Entry)।


4130
2018-06-30 23:28



तो एक साथ 2 मानचित्रों के माध्यम से लूप कैसे करें? एंट्रीसेट विधि का उपयोग कर? मैंने && का उपयोग करने की कोशिश की लेकिन यह काम नहीं करता है - DaMainBoss
दो iterators का प्रयोग करें। एक इटरेटर के उदाहरण के उपयोग के लिए स्वीकृत उत्तर देखें। - harto
एंट्रीसेट का उपयोग करने के लिए यह केवल अधिक कुशल है जब आपको दोनों चाबियाँ और मानों की आवश्यकता होती है। यदि आपको केवल एक या दूसरे की आवश्यकता है तो बस उस का उपयोग करें: stackoverflow.com/questions/3870064/... - rogerdpack
एक और महत्वपूर्ण बात, keySet () द्वारा सेट किया गया सेट और मानों () द्वारा संग्रहित संग्रह मूल मानचित्र द्वारा समर्थित हैं। यही है, यदि आप उनमें कोई संशोधन करते हैं तो वे मानचित्र में वापस दिखाई देंगे, हालांकि, उनमें से दोनों add () और addAll () विधियों का समर्थन नहीं करते हैं यानी आप सेट या नए मान में नई कुंजी नहीं जोड़ सकते संग्रह में। - sactiw
मूल्यों और चाबियों को प्राप्त करने के बारे में, पहले उपयोग करने के लिए यह आसान नहीं है foreach उदाहरण के साथ और लूप के अंदर मूल्य प्राप्त करें value = map.get(key)? का प्रदर्शन है entrySet और ऊँचा? - Marco Sulla


संदर्भ से निकाला गया जावा में एक मानचित्र पर कैसे Iterate:

एक से अधिक पुनरावृत्त करने के कई तरीके हैं Map जावा में आइए सबसे आम तरीकों पर जाएं और उनके फायदे और नुकसान की समीक्षा करें। चूंकि जावा में सभी मानचित्र मानचित्र इंटरफ़ेस को लागू करते हैं, इसलिए निम्न तकनीक किसी भी मानचित्र कार्यान्वयन के लिए काम करेगी (HashMap, TreeMap, LinkedHashMap, Hashtable, आदि।)

विधि # 1: फॉर-प्रत्येक लूप का उपयोग करके प्रविष्टियों पर इटरेट करना।

यह सबसे आम तरीका है और ज्यादातर मामलों में बेहतर है। यदि आपको लूप में नक्शा कुंजी और मान दोनों की आवश्यकता है तो इसका उपयोग किया जाना चाहिए।

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

ध्यान दें कि फॉर-प्रत्येक लूप जावा 5 में पेश किया गया था, इसलिए यह विधि केवल भाषा के नए संस्करणों में काम कर रही है। इसके अलावा एक फॉर-प्रत्येक लूप फेंक देगा NullPointerException यदि आप एक मानचित्र पर फिर से शुरू करने का प्रयास करते हैं जो शून्य है, तो फिर से शुरू करने से पहले आपको हमेशा शून्य संदर्भों की जांच करनी चाहिए।

विधि # 2: फॉर-प्रत्येक लूप का उपयोग करके चाबियों या मानों पर इटरेट करना।

यदि आपको मानचित्र से केवल चाबियाँ या मानों की आवश्यकता है, तो आप एंट्रीसेट के बजाय कीसेट या मानों पर फिर से सक्रिय हो सकते हैं।

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

// Iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}

// Iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}

यह विधि थोड़ा सा प्रदर्शन लाभ देती है entrySet पुनरावृत्ति (लगभग 10% तेज) और अधिक साफ है।

विधि # 3Iterator का उपयोग कर Iterating।

जेनरिक का उपयोग करना:

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());
}

जेनरिक के बिना:

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

आप फिर से शुरू करने के लिए एक ही तकनीक का उपयोग कर सकते हैं keySet या मूल्य।

यह विधि अनावश्यक लग सकती है, लेकिन इसके अपने फायदे हैं। सबसे पहले, जावा के पुराने संस्करणों में एक मानचित्र पर फिर से शुरू करने का यही एकमात्र तरीका है। दूसरी महत्वपूर्ण विशेषता यह है कि यह एकमात्र तरीका है जो आपको कॉल करके पुनरावृत्ति के दौरान मानचित्र से प्रविष्टियों को हटाने की अनुमति देता है iterator.remove()। यदि आप इसके लिए प्रत्येक पुनरावृत्ति के दौरान ऐसा करने का प्रयास करते हैं तो आपको "अप्रत्याशित परिणाम" मिलेंगे जावाडोक

एक प्रदर्शन बिंदु से यह विधि एक-प्रत्येक पुनरावृत्ति के बराबर है।

विधि # 4: चाबियों पर इटरेट करना और मूल्यों (अक्षम) की खोज करना।

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}

यह विधि # 1 के लिए क्लीनर विकल्प की तरह दिख सकता है, लेकिन व्यवहार में यह बहुत धीमी और अक्षम है क्योंकि कुंजी द्वारा मूल्य प्राप्त करने में समय लग सकता है (विभिन्न मानचित्र कार्यान्वयन में यह विधि विधि # 1 की तुलना में 20% -200% धीमी है )। यदि आपके पास FindBugs इंस्टॉल है, तो यह इसका पता लगाएगा और आपको अक्षम पुनरावृत्ति के बारे में चेतावनी देगा। इस विधि से बचा जाना चाहिए।

निष्कर्ष:

यदि आपको मानचित्र से केवल कुंजी या मान की आवश्यकता है, तो विधि # 2 का उपयोग करें। यदि आप जावा के पुराने संस्करण (5 से कम) या पुनरावृत्ति के दौरान प्रविष्टियों को हटाने की योजना बना रहे हैं, तो आपको विधि # 3 का उपयोग करना होगा। अन्यथा विधि # 1 का उपयोग करें।


740
2017-12-08 14:19



चलो छोटे caevet, जो कि मामले में जोड़ें ConcurrentMapएस, पुनरावृत्ति पर keySet() सामान्य रूप से दुर्घटनाग्रस्त हो जाएगा (पहले से एकत्रित कुंजी के लिए मान मौजूद नहीं हैं)। दूसरी तरफ इटरेटर या प्रविष्टियों का उपयोग सुरक्षित है (वे हमेशा मौजूदा वस्तुओं का संदर्भ लें)। - P Marecki
@arvind विधि # 4 कभी अक्षम कैसे होगा? परिभाषा के अनुसार, कॉलिंग get() हैश मैप के लिए हमेशा ओ (1) है। यह हैश मैप की परिभाषा है और उपयोगकर्ता ने हैश मैप के लिए कहा है। मुझे नहीं लगता कि यह इतना ऊंचा क्यों है। यदि आप किसी और के लिंक का संदर्भ देने जा रहे हैं, तो सुनिश्चित करें कि यह वास्तव में पूछे गए प्रश्न के लिए समझ में आता है। - ohbrobig


आप ए में प्रविष्टियों के माध्यम से पुनरावृत्त कर सकते हैं Map कई मायनों में। प्रत्येक कुंजी और मूल्य इस तरह प्राप्त करें:

Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
    System.out.println("Key " + e.getKey());
    System.out.println("Value " + e.getValue());
}

या आप कुंजी की सूची प्राप्त कर सकते हैं

Collection<?> keys = map.keySet();
for(Object key: keys){
    System.out.println("Key " + key);
    System.out.println("Value " + map.get(key));
}

यदि आप केवल सभी मान प्राप्त करना चाहते हैं और चाबियों से चिंतित नहीं हैं, तो आप इसका उपयोग कर सकते हैं:

Collection<?> values = map.values();

77
2018-06-30 23:43





for (Map.Entry<String, String> item : params.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}

70
2017-07-23 01:28





होशियार:

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

55
2017-08-11 10:01



यह वास्तव में इस पर निर्भर करता है कि आपको चाबियाँ चाहिए या नहीं। यदि नहीं, तो हैशकोड () को कॉल करने के लिए एंट्रीसेट () का उपयोग करना अधिक कुशल है। - icfantv
प्रत्येक पुनरावृत्ति के लिए map.get (कुंजी) स्मार्ट नहीं है - इसका तरीका धीमा है - ComputerEngineer88
map.entrySet () जो प्रविष्टियों को लौटाता है जिनमें पहले से ही कुंजी और मान दोनों शामिल हैं। इस तरह आपको हैशकोड () को कॉल करने और पुनरावृत्ति के दौरान हैश को खोजने की आवश्यकता नहीं है। - ComputerEngineer88
जावा 8 वाक्यविन्यास। अभी भी एंड्रॉइड विकास के लिए काम नहीं कर सकता है। "एंड्रॉइड का उद्देश्य किसी भी जावा एसई एपीआई संस्करण के साथ 100% संगत नहीं होना चाहिए, न कि 6 और न ही 8 और कोई भी ... जेआरई जावा रनटाइम पर्यावरण है जबकि जेडीके जावा डेवलपमेंट किट है। यह जेडीके है जिसे आपको चाहिए मौजूदा एंड्रॉइड एसडीके के साथ एंड्रॉइड एप्लिकेशन डेवलपमेंट के लिए। 9 दिसंबर, 2013 " स्रोत - jasonleonhard


निर्भर करता है। यदि आप जानते हैं कि आपको प्रत्येक प्रविष्टि की कुंजी और मूल्य दोनों की आवश्यकता होगी, तो उसके माध्यम से जाएं entrySet। यदि आपको केवल मूल्यों की आवश्यकता है, तो वहां है values() तरीका। और यदि आपको केवल चाबियाँ चाहिए, तो इसका उपयोग करें keyset()

एक बुरी आदत सभी चाबियों के माध्यम से फिर से शुरू होगी, और फिर लूप के भीतर, हमेशा करें map.get(key) मूल्य प्राप्त करने के लिए। यदि आप ऐसा कर रहे हैं, तो मैंने लिखा पहला विकल्प आपके लिए है।


40
2018-06-30 23:29



एक और महत्वपूर्ण बात, keySet () द्वारा सेट किया गया सेट और मानों () द्वारा संग्रहित संग्रह मूल मानचित्र द्वारा समर्थित हैं। यही है, यदि आप उनमें कोई संशोधन करते हैं तो वे मानचित्र में वापस दिखाई देंगे, हालांकि, उनमें से दोनों add () और addAll () विधियों का समर्थन नहीं करते हैं यानी आप सेट या नए मान में नई कुंजी नहीं जोड़ सकते संग्रह में। - sactiw