जावा हैशमैप: मूल्य से कुंजी कैसे प्राप्त करें?


451

यदि मेरे पास मूल्य है "foo", और HashMap<String> ftwजिसके लिए ftw.containsValue("foo")रिटर्न मिलता है true, तो मैं कैसे संबंधित कुंजी प्राप्त कर सकता हूं? क्या मुझे हैशमैप के माध्यम से लूप करना है? उसे करने का सबसे अच्छा तरीका कौन सा है?


72
ध्यान दें कि कोई एकल संबंधित कुंजी नहीं है - समान मान के लिए कई कुंजी हो सकती हैं।
CPerkins

1
@ स्पीकर
कुंभ राशि

यदि आपके पास वस्तुओं का एक छोटा संग्रह है, तो निरंतर बनाने पर विचार करें public static final String TIME = "time";औरproperties.put(TIME, PbActivityJpa_.time);
बशीर अल-मोमानी

शायद यह आपको मानचित्र से डेटा प्राप्त करने में मदद कर सकता है और आप किसी प्रकार का प्रसंस्करण भी कर सकते हैं। frugalisminds.com/java/java-8-stream-map-examples
संजय-देव

जवाबों:


215

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

BidiMap संग्रह पुस्तकालय में इंटरफ़ेस एक द्वि-दिशात्मक नक्शे, आप (सामान्य नक्शे की तरह) एक मूल्य के लिए एक महत्वपूर्ण मैप करने के लिए अनुमति देता है, और यह भी एक प्रमुख करने के लिए एक मूल्य मैप करने के लिए, इस प्रकार आप दोनों दिशाओं में लुकअप प्रदर्शन करने के लिए अनुमति देता है। मान के लिए एक कुंजी प्राप्त करना getKey () विधि द्वारा समर्थित है

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

अपडेट करें

यदि आप जावा कलेक्शंस एपीआई पर भरोसा करना चाहते हैं, तो आपको मानचित्र में मूल्य सम्मिलित करने के समय कुंजियों और मूल्यों के बीच 1: 1 संबंध सुनिश्चित करना होगा। ऐसा करना मुश्किल लेकिन कहना आसान है।

एक बार जब आप यह सुनिश्चित कर सकते हैं कि, मानचित्र में प्रविष्टियों (मैपिंग) के सेट को प्राप्त करने के लिए entrySet () विधि का उपयोग करें । एक बार जब आप सेट प्राप्त कर लेते हैं जिसका प्रकार Map.Entry है , प्रविष्टियों के माध्यम से पुनरावृति, अपेक्षित के खिलाफ संग्रहीत मूल्य की तुलना करें , और संबंधित कुंजी प्राप्त करें

अद्यतन # 2

जेनरिक के साथ बीड़ी के नक्शे के लिए समर्थन गूगल अमरूद और रिफैक्टर्ड कॉमन्स-कलेक्शंस लाइब्रेरी में पाया जा सकता है (बाद वाला अपाचे प्रोजेक्ट नहीं है)। अपाचे कॉमन्स कलेक्शंस में लापता जेनेरिक समर्थन को इंगित करने के लिए एस्को का धन्यवाद। जेनरिक के साथ संग्रह का उपयोग करना अधिक अनुरक्षण कोड बनाता है।


23
... और यदि आप जेनरिक और उस सभी आधुनिक सामानों को पसंद करते हैं, तो Google कलेक्शंस में BiMap है जहाँ आप biMap.inverse () (get) (वैल्यू) कॉल करके मुख्य मिलान निर्दिष्ट मान प्राप्त कर सकते हैं;
Esko

1
हाँ, अपाचे कॉमन्स कलेक्शंस जेनरिक का समर्थन नहीं करता है। हालाँकि, आपके द्वारा इंगित किए गए Google संग्रह हैं (जो मैं अभी तक उपयोग नहीं करता हूं - कोई 1.0 रिलीज़ अभी तक नहीं), और जेनरिक के समर्थन के साथ रिफैक्टेड कॉमन्स-कलेक्शंस है। आप इसे स्रोत स्रोत
विनीत रेनॉल्ड्स

2
Google संग्रह कॉमन्स-संग्रह का एक परिष्कृत संस्करण नहीं है।
व्हिस्कीसिएर

12
@whiskeysierra: मुझे नहीं लगता कि कोई भी (वर्तमान में) ऐसा कह रहा है।
huff

2
अपाचे कलेक्शंस अब जेनेरिक commons.apache.org/proper/commons-collections/javadocs/…
kervin

603

यदि आपकी डेटा संरचना में कुंजियों और मूल्यों के बीच कई-से-एक मैपिंग है, तो आपको प्रविष्टियों पर चलना चाहिए और सभी उपयुक्त कुंजियों को चुनना चाहिए:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    Set<T> keys = new HashSet<T>();
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            keys.add(entry.getKey());
        }
    }
    return keys;
}

एक-से-एक संबंध के मामले में , आप पहली मिलान की गई कुंजी वापस कर सकते हैं:

public static <T, E> T getKeyByValue(Map<T, E> map, E value) {
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            return entry.getKey();
        }
    }
    return null;
}

जावा 8 में:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    return map.entrySet()
              .stream()
              .filter(entry -> Objects.equals(entry.getValue(), value))
              .map(Map.Entry::getKey)
              .collect(Collectors.toSet());
}

इसके अलावा, अमरूद उपयोगकर्ताओं के लिए, BiMap उपयोगी हो सकता है। उदाहरण के लिए:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);

3
क्या आप प्रदर्शन के बारे में कुछ कह सकते हैं? अधिक अनुकूलित क्या होगा? यह या बीड़ीपापा?
tasomaniac

मैंने एक ही समाधान सोचा है, मैंने इसे बेशक बदल दिया है लेकिन मुझे इसकी दक्षता पर संदेह है जब यह वास्तव में बड़े संग्रह की बात आती है।
6

3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap में समय की जटिलता है o(1)। यदि आप मूल्यों से अधिक परेशान कर रहे हैं तो यह प्रदर्शन को मार देगा। यदि आप एक चाहते हैं better performanceऔर एक one-oneरिश्ता है, तो आप another mapकहाँ उपयोग कर सकते हैंvalue is a key
veer7

3
मैं बदलने के लिए सलाह देते हैं .filter(entry -> entry.getValue().equals(value))साथ के रूप में के बारे में कोई बयान क्षमता बनाया गया था। इसके अलावा, आप के साथ बदल सकते हैं.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Holger

मुझे <T> getKeysByValue () सेट करने से पहले <T, E> नोटेशन को समझने में कठिनाई हो रही है ... क्या बात है .... इसका उपयोग किए बिना इसे करने का अलग तरीका? धन्यवाद
विचार

76
public class NewClass1 {

    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()) {
            if (entry.getValue().equals("c")) {
                System.out.println(entry.getKey());
            }
        }
    }
}

कुछ अतिरिक्त जानकारी ... आपके लिए उपयोगी हो सकती है

यदि आपका हैशमैप वास्तव में बड़ा है तो उपरोक्त विधि अच्छी नहीं हो सकती है। यदि आपके हैशमैप में अनूठे मान मानचित्रण की कुंजी है, तो आप एक और हैशमैप बनाए रख सकते हैं जिसमें मान से कुंजी तक मानचित्रण है।

यानी आपको दो हैशमैप बनाए रखने होंगे

1. Key to value

2. Value to key 

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


19

मुझे लगता है कि आपकी पसंद हैं

  • इसके लिए बनाए गए मानचित्र कार्यान्वयन का उपयोग करें, जैसे BiMap Google संग्रह से । ध्यान दें कि Google संग्रह BiMap को विशिष्ट मानों के साथ-साथ कुंजियों की भी आवश्यकता है, लेकिन यह दोनों दिशाओं के प्रदर्शन में उच्च प्रदर्शन प्रदान करता है
  • मैन्युअल रूप से दो मानचित्र बनाए रखें - एक कुंजी के लिए -> मूल्य, और मूल्य के लिए एक और मानचित्र -> कुंजी
  • entrySet()मूल्य से मेल खाने वाली कुंजी खोजने के लिए और के माध्यम से Iterate करें। यह सबसे धीमी विधि है, क्योंकि इसे पूरे संग्रह के माध्यम से पुनरावृत्ति की आवश्यकता होती है, जबकि अन्य दो विधियों की आवश्यकता नहीं होती है।

19

आप अपने मानचित्र संरचना में कुंजी, मूल्य जोड़ी और इसके व्युत्क्रम दोनों को सम्मिलित कर सकते हैं

map.put("theKey", "theValue");
map.put("theValue", "theKey");

Map.get ("theValue") का उपयोग करके फिर "TheKey" लौटाएगा।

यह एक त्वरित और गंदा तरीका है जो मैंने निरंतर नक्शे बनाए हैं, जो केवल कुछ चुनिंदा डेटासेट के लिए काम करेंगे:

  • केवल 1 से 1 जोड़े शामिल हैं
  • मानों का सेट कुंजियों के सेट से अलग है (1-> 2, 2-> 3 इसे तोड़ता है)

4
यह वास्तव में सही नहीं है। इसके लिए केवल 1-1 की आवश्यकता नहीं है, बल्कि यह भी है कि मानों का समूह कुंजियों के समूह से असहमति रखता है। आप इसे जीवनी के नक्शे {1 -> 2, 2 -> 3}: 2 पर लागू नहीं कर सकते हैं, दोनों एक मूल्य और एक कुंजी है।
लुइस ए। फ्लोरिट

15

अपने खुद के कार्यान्वयन के साथ मानचित्र सजाने

class MyMap<K,V> extends HashMap<K, V>{

    Map<V,K> reverseMap = new HashMap<V,K>();

    @Override
    public V put(K key, V value) {
        // TODO Auto-generated method stub
        reverseMap.put(value, key);
        return super.put(key, value);
    }

    public K getKey(V value){
        return reverseMap.get(value);
    }
}

मुझे लगता है कि यह एक दिलचस्प दृष्टिकोण है, हालांकि संबंध 1: 1 होना चाहिए, मैं पूरी तरह से हाशपैप से छुटकारा पाऊंगा और मानचित्र <के, वी> इंटरफ़ेस को लागू करने के बजाय दोनों, मूल्यों और कुंजियों के डुप्लिकेट से बचने के लिए।
फ्रेंक मारजोआ

11

कोई स्पष्ट जवाब नहीं है, क्योंकि कई कुंजी एक ही मूल्य के लिए मैप कर सकते हैं। यदि आप अपने स्वयं के कोड के साथ अनूठे-नेस लागू कर रहे हैं, तो सबसे अच्छा समाधान एक वर्ग बनाना है जो दोनों दिशाओं में मैपिंग को ट्रैक करने के लिए दो हाशमैप का उपयोग करता है।


11

उस मान को मैप करने वाली सभी कुंजियों को खोजने के लिए, का उपयोग करके हैशमैप में सभी जोड़े के माध्यम से पुनरावृति करें map.entrySet()


4
यह समाधान बहुत ही गहन है, उस बिंदु तक जहां यह बड़े हैशमैप पर अव्यवहारिक है।
जोहोट २००

10

जावा 8 का उपयोग करना:

ftw.forEach((key, value) -> {
    if (value.equals("foo")) {
        System.out.print(key);
    }
});

6
value=="foo" यह काम नहीं करेगा। equalsस्ट्रिंग्स की तुलना करने के लिए इस्तेमाल किया जाना चाहिए।
एंटोन बालानियुक

@ एटन, सच जब तक valueनजरबंद नहीं किया गया है।
फ्रॉडोडॉट

9

यदि आप मानचित्र को अपने कोड में बनाते हैं, तो मानचित्र में कुंजी और मान को एक साथ रखने का प्रयास करें:

public class KeyValue {
    public Object key;
    public Object value;
    public KeyValue(Object key, Object value) { ... }
}

map.put(key, new KeyValue(key, value));

फिर जब आपके पास एक मूल्य होता है, तो आपके पास चाबी भी होती है।


3
चतुर, लेकिन क्या होगा यदि समान मूल्य वाले 2 या अधिक KeyValue ऑब्जेक्ट हैं? किस कुंजी का चयन करना चाहिए?
विनीत रेनॉल्ड्स

2
@ विनीत, मैं यह नहीं देखता कि यह दृष्टिकोण ओपी के प्रश्न को कैसे हल करता है। "तब जब आपके पास मूल्य है, तो आपके पास क्या मतलब है?"
कियान्ग ली

9

मुझे लगता है कि यह सबसे अच्छा समाधान है, मूल पता: Java2s

    import java.util.HashMap;
    import java.util.Map;

        public class Main {

          public static void main(String[] argv) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("1","one");
            map.put("2","two");
            map.put("3","three");
            map.put("4","four");

            System.out.println(getKeyFromValue(map,"three"));
          }


// hm is the map you are trying to get value from it
          public static Object getKeyFromValue(Map hm, Object value) {
            for (Object o : hm.keySet()) {
              if (hm.get(o).equals(value)) {
                return o;
              }
            }
            return null;
          }
        }

एक आसान उपयोग: यदि आप सभी डेटा को hasMap में रखते हैं और आपके पास आइटम = "ऑटोमोबाइल" है, तो आप hashMap में इसकी कुंजी देख रहे हैं। यह अच्छा उपाय है।

getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));

7

मुझे डर है कि आपको बस अपने नक्शे को पुनरावृत्त करना होगा। सबसे कम मैं साथ आ सकता है:

Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry<String,String> entry = iter.next();
    if (entry.getValue().equals(value_you_look_for)) {
        String key_you_look_for = entry.getKey();
    }
}


6

ऐसा लगता है कि आपके लिए सबसे अच्छा तरीका है प्रविष्टियों का उपयोग करना, map.entrySet()क्योंकि map.containsValue()यह वैसे भी करता है।


हां, ठीक यही है। लेकिन निश्चित रूप से यह सच हो जाता है जैसे ही यह एक मूल्य पाता है जिसके लिए। असमान सत्य है, जैसा कि ओपी को शायद करने की जरूरत नहीं है।
CPerkins

1
खैर, प्रविष्टियों पर पुनरावृत्ति करना कुंजी के साथ वापस आ सकता है जैसे ही यह एक मिलान मूल्य भी पाता है। कई मैचों में कोई चिंता नहीं थी।
जोनास के

6

Android विकास लक्ष्यीकरण API <19 के लिए, विटाली फेडोरेंको वन-टू-वन रिलेशन सॉल्यूशन काम नहीं करता क्योंकि Objects.equalsइसे लागू नहीं किया गया है। यहाँ एक आसान विकल्प है:

public <K, V> K getKeyByValue(Map<K, V> map, V value) {
    for (Map.Entry<K, V> entry : map.entrySet()) {
            if (value.equals(entry.getValue())) {
            return entry.getKey();
        }
    }
    return null;
}

यह समाधान मेरे लिए काम करता है; एक पुरातात्विक Android संस्करण के लिए भी विकसित हो रहा है, मेरे मामले में एक "onMarkerClick" इवेंट में मैप में Google मैप मार्कर की कुंजी प्राप्त करने के लिए। प्रविष्टि बदलना I काम करता है; लेकिन कुंजियों को पुनरावृत्त करना और उन्हें प्राप्त () के साथ प्रविष्टियों से मेल खाना, और आउटपुट की तुलना करना, नहीं किया।
टोबे विल्सन

3

आप नीचे का उपयोग कर सकते हैं:

public class HashmapKeyExist {
    public static void main(String[] args) {
        HashMap<String, String> hmap = new HashMap<String, String>();
        hmap.put("1", "Bala");
        hmap.put("2", "Test");

        Boolean cantain = hmap.containsValue("Bala");
        if(hmap.containsKey("2") && hmap.containsValue("Test"))
        {
            System.out.println("Yes");
        }
        if(cantain == true)
        {
            System.out.println("Yes"); 
        }

        Set setkeys = hmap.keySet();
        Iterator it = setkeys.iterator();

        while(it.hasNext())
        {
            String key = (String) it.next();
            if (hmap.get(key).equals("Bala"))
            {
                System.out.println(key);
            }
        }
    }
}

यह अच्छा है कि आप उपयोगी सामान प्रदान करना चाहते हैं, लेकिन यह "कोड केवल" उत्तर नहीं होना चाहिए और कोड स्वयं कोड गंध से भरा नहीं होना चाहिए।
टॉम

2

हां, आपको हैशमैप के माध्यम से लूप करना होगा, जब तक कि आप इन विभिन्न उत्तरों के सुझाव के आधार पर कुछ लागू नहीं करते हैं। एंट्रीसेट के साथ फ़िडलिंग करने के बजाय, मुझे बस उस सेट पर कीसेट (), iterate मिलेगा, और (पहली) कुंजी रखें जिससे आपको आपका मिलान मूल्य मिल सके। यदि आपको उस मूल्य से मेल खाने वाली सभी कुंजियों की आवश्यकता है, तो जाहिर है आपको पूरी बात करनी होगी।

जैसा कि जोनास सुझाव देते हैं, यह पहले से ही हो सकता है कि इसमें शामिल है वेवल्यू विधि, इसलिए आप बस उस परीक्षण को एक साथ छोड़ सकते हैं, और बस हर बार पुनरावृत्ति कर सकते हैं (या शायद कंपाइलर पहले से ही अतिरेक को समाप्त कर देगा, जो जानता है)।

इसके अलावा, अन्य उत्तरों के सापेक्ष, यदि आपका रिवर्स मैप दिखता है

Map<Value, Set<Key>>

यदि आप उस क्षमता की आवश्यकता है, तो गैर-अद्वितीय कुंजी-> मूल्य मैपिंग से निपट सकते हैं। दो मानचित्रों का उपयोग करके लोगों द्वारा सुझाए गए किसी भी समाधान में यह ठीक होगा।


2

आप निम्नलिखित कोड का उपयोग करके मूल्यों का उपयोग करके कुंजी प्राप्त कर सकते हैं।

ArrayList valuesList = new ArrayList();
Set keySet = initalMap.keySet();
ArrayList keyList = new ArrayList(keySet);

for(int i = 0 ; i < keyList.size() ; i++ ) {
    valuesList.add(initalMap.get(keyList.get(i)));
}

Collections.sort(valuesList);
Map finalMap = new TreeMap();
for(int i = 0 ; i < valuesList.size() ; i++ ) {
    String value = (String) valuesList.get(i);

    for( int j = 0 ; j < keyList.size() ; j++ ) {
        if(initalMap.get(keyList.get(j)).equals(value)) {
            finalMap.put(keyList.get(j),value);
        }   
    }
}
System.out.println("fianl map ---------------------->  " + finalMap);

2
public static class SmartHashMap <T1 extends Object, T2 extends Object> {
    public HashMap<T1, T2> keyValue;
    public HashMap<T2, T1> valueKey;

    public SmartHashMap(){
        this.keyValue = new HashMap<T1, T2>();
        this.valueKey = new HashMap<T2, T1>();
    }

    public void add(T1 key, T2 value){
        this.keyValue.put(key, value);
        this.valueKey.put(value, key);
    }

    public T2 getValue(T1 key){
        return this.keyValue.get(key);
    }

    public T1 getKey(T2 value){
        return this.valueKey.get(value);
    }

}

मुझे लगता है कि स्पष्टीकरण को जोड़कर इस उत्तर को बेहतर बनाया जा सकता है।
योनातन

2
-1। मैंने इसे Stringकुंजी और मूल्य के रूप में परीक्षण किया । जब मैं कॉल करता हूं map.add("1", "2"); map.add("1","3");तो मैं कॉल कर सकता हूं map.getKey("2");और पुनर्प्राप्त कर सकता हूं "1", भले ही "1"इसके लिए कुंजी हो "3"
jlordo

@ जोनाथन इस वर्ग के पीछे का विचार है कि रिवर्स मैपिंग के साथ एक और हैशपॉप रखा जाए ताकि एक कुंजी से मूल्य प्राप्त करने के अलावा, आप एक मूल्य से एक कुंजी प्राप्त कर सकें। टी 1 और टी 2 कक्षाएं थोड़ा भ्रमित हैं; शायद सचमुच उन्हें कुंजी और मान के बजाय नाम दें? यद्यपि मुझे डेटा और आप जो चाहते हैं उसके आधार पर एक से अधिक मूल्य या बदले में एक से अधिक कुंजी प्राप्त करने की क्षमता की उम्मीद होगी। सावधानी के साथ प्रयोग करें
चिकोविट्ज़

1
@theknightwhosaysni "1" "2" (अब) की कुंजी नहीं है। यह आपके प्रश्न का उत्तर भी है, कॉलिंग getValue("1")वापस आ जाएगी 3
jlordo

क्षमा करें jlordo, मुझे मानक हशमैप व्यवहार के बारे में गलत समझा गया था: आप सही हैं कि एक कुंजी के लिए नया मान जोड़ने से पुराने मूल्य को बदलना चाहिए
Chicowitz

2

जावा 8 में

map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
    .forEach(entry -> System.out.println(entry.getKey()));

2
public static String getKey(Map<String, Integer> mapref, String value) {
    String key = "";
    for (Map.Entry<String, Integer> map : mapref.entrySet()) {
        if (map.getValue().toString().equals(value)) {
            key = map.getKey();
        }
    }
    return key;
}

नक्शा <स्ट्रिंग, पूर्णांक> नक्शा = नया हैशपेयर <स्ट्रिंग, पूर्णांक> (); map.put ("ए", 1); map.put ("बी", 2); map.put ("सी", 3); map.put ("डी", 4); // System.out.println (map); System.out.println (getKey (मानचित्र, "4"));
कमाल इंडिया

1
यदि एकाधिक कुंजियों का समान मान हो तो क्या होता है?
Cà phê Junen

जब यू पास कई कुंजी एक ही मूल्य है, हम परिणाम के रूप में अंतिम कुंजी मिल जाएगा। उदाहरण: A 1, B 1, C 1, D 2 आउटपुट: यदि हम 1 मान पास करते हैं, तो आउटपुट C होगा
आश्चर्यजनक भारत

@AmazingIndia यह गारंटी नहीं है और पूरी तरह से विशिष्ट मानचित्र कार्यान्वयन पर निर्भर करता है। उदाहरण के लिए HashMap एक आदेश की गारंटी नहीं देता है, इसलिए आपको पता नहीं है कि यहां क्या आउटपुट वापस आएगा।
नील्स डौकेट

1
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class ValueKeysMap<K, V> extends HashMap <K,V>{
    HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>();

    @Override
    public boolean containsValue(Object value) {
        return ValueKeysMap.containsKey(value);
    }

    @Override
    public V put(K key, V value) {
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            keys.add(key);
        } else {
            Set<K> keys = new HashSet<K>();
            keys.add(key);
            ValueKeysMap.put(value, keys);
        }
        return super.put(key, value);
    }

    @Override
    public V remove(Object key) {
        V value = super.remove(key);
        Set<K> keys = ValueKeysMap.get(value);
        keys.remove(key);
        if(keys.size() == 0) {
           ValueKeysMap.remove(value);
        }
        return value;
    }

    public Set<K> getKeys4ThisValue(V value){
        Set<K> keys = ValueKeysMap.get(value);
        return keys;
    }

    public boolean valueContainsThisKey(K key, V value){
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            return keys.contains(key);
        }
        return false;
    }

    /*
     * Take care of argument constructor and other api's like putAll
     */
}

1
/**
 * This method gets the Key for the given Value
 * @param paramName
 * @return
 */
private String getKeyForValueFromMap(String paramName) {
    String keyForValue = null;
    if(paramName!=null)) {
        Set<Entry<String,String>> entrySet = myMap().entrySet();
        if(entrySet!=null && entrySet.size>0) {
            for(Entry<String,String> entry : entrySet) {
                if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) {
                    keyForValue = entry.getKey();
                }
            }
        }
    }
    return keyForValue;
}

1
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class M{
public static void main(String[] args) {

        HashMap<String, List<String>> resultHashMap = new HashMap<String, List<String>>();

        Set<String> newKeyList = resultHashMap.keySet();


        for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) {
            String hashKey = (String) iterator.next();

            if (!newKeyList.contains(originalHashMap.get(hashKey))) {
                List<String> loArrayList = new ArrayList<String>();
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            } else {
                List<String> loArrayList = resultHashMap.get(originalHashMap
                        .get(hashKey));
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            }
        }

        System.out.println("Original HashMap : " + originalHashMap);
        System.out.println("Result HashMap : " + resultHashMap);
    }
}

1

एक पतले आवरण का उपयोग करें: HMap

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HMap<K, V> {

   private final Map<K, Map<K, V>> map;

   public HMap() {
      map = new HashMap<K, Map<K, V>>();
   }

   public HMap(final int initialCapacity) {
      map = new HashMap<K, Map<K, V>>(initialCapacity);
   }

   public boolean containsKey(final Object key) {
      return map.containsKey(key);
   }

   public V get(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }

   public K getKey(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.keySet().iterator().next();
      return null;
   }

   public V put(final K key, final V value) {
      final Map<K, V> entry = map
            .put(key, Collections.singletonMap(key, value));
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }
}

1

मेरे 2 सेंट। आप किसी सरणी में कुंजी प्राप्त कर सकते हैं और फिर सरणी के माध्यम से लूप कर सकते हैं। यदि यह नक्शा बहुत बड़ा है, तो यह इस कोड ब्लॉक के प्रदर्शन को प्रभावित करेगा, जहाँ आपको पहले एक सरणी में कुंजियाँ मिल रही हैं जो कुछ समय का उपभोग कर सकती हैं और फिर आप लूप कर रहे हैं। अन्यथा छोटे नक्शों के लिए यह ठीक होना चाहिए।

String[] keys =  yourMap.keySet().toArray(new String[0]);

for(int i = 0 ; i < keys.length ; i++){
    //This is your key    
    String key = keys[i];

    //This is your value
    yourMap.get(key)            
}

और किसी को उस दृष्टिकोण का उपयोग क्यों करना चाहिए? जैसा कि आपने पहले ही कहा, अन्य दृष्टिकोणों की तुलना में प्रदर्शन अधिक खराब होगा।
टॉम

1

मुझे लगता है कीसेट () वैल्यू की मैपिंग करने के लिए अच्छी तरह से हो सकती है, और इसमें एंट्री () की तुलना में बेहतर कोडिंग स्टाइल है।

उदाहरण के लिए:

मान लीजिए कि आपके पास एक हैशपॉप नक्शा है , ArrayList Res , एक मान जिसे आप सभी कुंजी ढूंढना चाहते हैं मैपिंग को , फिर Res के लिए कुंजी स्टोर करें

आप नीचे कोड लिख सकते हैं:

    for (int key : map.keySet()) {
        if (map.get(key) == value) {
            res.add(key);
        }
    }

एंट्रीसेट () के बजाय नीचे का उपयोग करें:

    for (Map.Entry s : map.entrySet()) {
        if ((int)s.getValue() == value) {
            res.add((int)s.getKey());
        }
    }

आशा है ये मदद करेगा :)


map.get(key) == valueजब आप संदर्भों की तुलना कर रहे हों तो वस्तुओं की समानता की जाँच करना अच्छा विचार नहीं है। ऑब्जेक्ट समानता हमेशा उनके उपयोग करना चाहिए.equals()
frododot

1

जबकि यह सीधे सवाल का जवाब नहीं देता है, यह संबंधित है।

इस तरह से आपको इसे बनाते / बनाते रहने की आवश्यकता नहीं है। बस एक बार रिवर्स मैप बनाएं और आपको जो चाहिए वह प्राप्त करें।

/**
 * Both key and value types must define equals() and hashCode() for this to work.
 * This takes into account that all keys are unique but all values may not be.
 *
 * @param map
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<V, List<K>> reverseMap(Map<K,V> map) {
    if(map == null) return null;

    Map<V, List<K>> reverseMap = new ArrayMap<>();

    for(Map.Entry<K,V> entry : map.entrySet()) {
        appendValueToMapList(reverseMap, entry.getValue(), entry.getKey());
    }

    return reverseMap;
}


/**
 * Takes into account that the list may already have values.
 * 
 * @param map
 * @param key
 * @param value
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> appendValueToMapList(Map<K, List<V>> map, K key, V value) {
    if(map == null || key == null || value == null) return map;

    List<V> list = map.get(key);

    if(list == null) {
        List<V> newList = new ArrayList<>();
        newList.add(value);
        map.put(key, newList);
    }
    else {
        list.add(value);
    }

    return map;
}

0

यह ध्यान रखना महत्वपूर्ण है कि इस प्रश्न के बाद से, अपाचे कलेक्शंस जेनेरिक बीड़ीमैप का समर्थन करता है । इसलिए कुछ शीर्ष मतदान जवाब अब उस बिंदु पर सटीक नहीं हैं।

एक Serialized BidiMap के लिए जो डुप्लिकेट मानों का समर्थन करता है (1-से-कई परिदृश्य) MapDB.org पर भी विचार करें


0
  1. यदि आप मूल्य से कुंजी प्राप्त करना चाहते हैं, तो बिदिमाप (द्वि-दिशात्मक नक्शे) का उपयोग करना सबसे अच्छा है, तो आप ओ (1) समय में मूल्य से कुंजी प्राप्त कर सकते हैं।

    लेकिन, इसके साथ दोष यह है कि आप केवल अद्वितीय कीसेट और वीसेट का उपयोग कर सकते हैं।

  2. एक डेटा संरचना है जिसे टेबल इन जावा कहा जाता है , जो नक्शे के नक्शे की तरह और कुछ नहीं है

    टेबल <ए, बी, सी> == नक्शा <ए, नक्शा <बी, सी>>

    यहाँ आप map<B,C>क्वेरी करके प्राप्त कर सकते हैं T.row(a);, और आप map<A,C>क्वेरी करके भी प्राप्त कर सकते हैंT.column(b);

अपने विशेष मामले में, कुछ स्थिर के रूप में C डालें।

तो, यह <a1, b1, 1> <a2, b2, 1>, ...

इसलिए, यदि आप T.row (a1) ---> रिटर्न मैप्स ऑफ -> के माध्यम से पाते हैं, तो इस लौटे हुए मैप की कीसेट प्राप्त करें।

यदि आपको कुंजी मान खोजने की आवश्यकता है, तो T.column (b2) -> रिटर्न मैप ऑफ -> रिटर्न मैप की कीसेट प्राप्त करें।

पिछले मामले में लाभ:

  1. कई मूल्यों का उपयोग कर सकते हैं।
  2. बड़े डेटा सेट का उपयोग करते समय अधिक कुशल।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.