527

If I have the value "foo", and a HashMap<String> ftw for which ftw.containsValue("foo") returns true, how can I get the corresponding key? Do I have to loop through the hashmap? What is the best way to do that?

Nick Heiner
  • 119,074
  • 188
  • 476
  • 699

40 Answers40

661

If your data structure has many-to-one mapping between keys and values you should iterate over entries and pick all suitable keys:

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

In case of one-to-one relationship, you can return the first matched key:

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

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

Also, for Guava users, BiMap may be useful. For example:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);
Pang
  • 9,564
  • 146
  • 81
  • 122
Vitalii Fedorenko
  • 110,878
  • 29
  • 149
  • 111
  • 4
    Can you say anything about the performance? What will be more optimized? This or BidiMap? – tasomaniac Aug 27 '13 at 13:41
  • I have thought the same solution, I have upvoted it of course but I doubt on its efficiency when it comes to really large Collections. – arjacsoh Sep 10 '13 at 06:59
  • 3
    http://stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap has time complexity `o(1)`. If you are iterating over the values then it will kill the performance. If you want a `better performance` and has a `one-one` relationship, you can use `another map` where `value is a key` – veer7 Apr 09 '15 at 10:03
  • 4
    I recommend to replace `.filter(entry -> entry.getValue().equals(value))` with `.filter(entry ->`[`Objects.equals`](http://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#equals-java.lang.Object-java.lang.Object-)`(entry.getValue(), value))` as no statement about `null`ability was made. Further, you can replace `.map(entry -> entry.getKey())` with `.map(Map.Entry::getKey)` – Holger Apr 21 '15 at 09:37
  • i'm having difficulty understanding the notation before Set getKeysByValue()...what's the point....different way to do it without using that? thanks – ponderingdev Dec 23 '16 at 05:50
  • **Call requires API Level 24: java.util.Collection#stream** – Aliton Oliveira May 15 '20 at 19:58
241

If you choose to use the Commons Collections library instead of the standard Java Collections framework, you can achieve this with ease.

The BidiMap interface in the Collections library is a bi-directional map, allowing you to map a key to a value (like normal maps), and also to map a value to a key, thus allowing you to perform lookups in both directions. Obtaining a key for a value is supported by the getKey() method.

There is a caveat though, bidi maps cannot have multiple values mapped to keys, and hence unless your data set has 1:1 mappings between keys and values, you cannot use bidi maps.


If you want to rely on the Java Collections API, you will have to ensure the 1:1 relationship between keys and values at the time of inserting the value into the map. This is easier said than done.

Once you can ensure that, use the entrySet() method to obtain the set of entries (mappings) in the Map. Once you have obtained the set whose type is Map.Entry, iterate through the entries, comparing the stored value against the expected, and obtain the corresponding key.


Support for bidi maps with generics can be found in Google Guava and the refactored Commons-Collections libraries (the latter is not an Apache project). Thanks to Esko for pointing out the missing generic support in Apache Commons Collections. Using collections with generics makes more maintainable code.


Since version 4.0 the official Apache Commons Collections™ library supports generics.

See the summary page of the "org.apache.commons.collections4.bidimap" package for the list of available implementations of the BidiMap, OrderedBidiMap and SortedBidiMap interfaces that now support Java generics.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • 26
    ...and if you like Generics and all that modern stuff, Google Collections has BiMap where you can get key matching specified value by calling biMap.inverse().get(value); – Esko Sep 05 '09 at 20:15
  • 1
    Yes, Apache Commons Collections doesn't support generics. However, there is Google Collections as you've pointed out (which I don't use yet - no 1.0 release yet), and there is the refactored Commons-Collections with support for Generics. You'll find this as a Sourceforge project @ http://sourceforge.net/projects/collections/ – Vineet Reynolds Sep 05 '09 at 20:29
  • 2
    The Google Collections are **not** a refactored version of Commons-Collections. – whiskeysierra Aug 09 '10 at 16:42
  • 14
    @whiskeysierra: I don't think anyone is (currently) saying so. – huff Sep 29 '11 at 03:00
  • It looks like Apache Commons will get a BidiMap with generics support in release 4.0 (currently in alpha release): http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html – Ogre Psalm33 Oct 21 '13 at 13:05
  • Is having two separate lists for keys and values a bad way to solve this problem? If you know the index of a key in the list of keys, you can get the value from that same index in the values list. – Price Oct 12 '14 at 06:22
  • 4
    Apache Collections now supports generics https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/bidimap/package-summary.html – kervin May 31 '15 at 16:28
  • guava's HashBiMap.create() – Aquarius Power Mar 26 '17 at 21:38
  • If you do have multiple values (and potentially multiple keys) you could extend HashMap to have ArrayList's for key and value then override get() iterating over key values using foreach(k, v). You can thereafter search by any of several keys and/or values and return the other. ;-) – Adam D. Mar 11 '23 at 22:59
89
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());
            }
        }
    }
}

Some additional info... May be useful to you

Above method may not be good if your hashmap is really big. If your hashmap contain unique key to unique value mapping, you can maintain one more hashmap that contain mapping from Value to Key.

That is you have to maintain two hashmaps

1. Key to value

2. Value to key 

In that case you can use second hashmap to get key.

Fathah Rehman P
  • 8,401
  • 4
  • 40
  • 42
27

You could insert both the key,value pair and its inverse into your map structure

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

Using map.get("theValue") will then return "theKey".

It's a quick and dirty way that I've made constant maps, which will only work for a select few datasets:

  • Contains only 1 to 1 pairs
  • Set of values is disjoint from the set of keys (1->2, 2->3 breaks it)
Chicowitz
  • 5,759
  • 5
  • 32
  • 38
  • 4
    This is not really correct. This does not only requires 1-1, but also that the set of values is disjoint from the set of keys. You can't apply this to the bijective map {1 -> 2, 2 -> 3}: 2 is both a value and a key. – Luis A. Florit Feb 04 '16 at 00:30
23

I think your choices are

  • Use a map implementation built for this, like the BiMap from google collections. Note that the google collections BiMap requires uniqueless of values, as well as keys, but it provides high performance in both directions performance
  • Manually maintain two maps - one for key -> value, and another map for value -> key
  • Iterate through the entrySet() and to find the keys which match the value. This is the slowest method, since it requires iterating through the entire collection, while the other two methods don't require that.
jpaugh
  • 6,634
  • 4
  • 38
  • 90
Chi
  • 22,624
  • 6
  • 36
  • 37
20

Using Java 8:

ftw.forEach((key, value) -> {
    if (value.equals("foo")) {
        System.out.print(key);
    }
});
phani
  • 507
  • 2
  • 6
  • 18
19

Decorate map with your own implementation

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);
    }
}
Thiago Sá
  • 832
  • 9
  • 22
ABHI
  • 191
  • 1
  • 2
  • I think this is an interesting approach, though since the relation has to be 1:1, I'd get rid of HashMap altogether and implement Map interface instead so to avoid duplicates of both, values and keys. – Fran Marzoa Oct 11 '16 at 09:21
12

There is no unambiguous answer, because multiple keys can map to the same value. If you are enforcing unique-ness with your own code, the best solution is to create a class that uses two Hashmaps to track the mappings in both directions.

recursive
  • 83,943
  • 34
  • 151
  • 241
12

To find all the keys that map to that value, iterate through all the pairs in the hashmap, using map.entrySet().

SkyWalker
  • 28,384
  • 14
  • 74
  • 132
wsorenson
  • 5,701
  • 6
  • 32
  • 29
12

If you build the map in your own code, try putting the key and value in the map together:

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

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

Then when you have a value, you also have the key.

David Tinker
  • 9,383
  • 9
  • 66
  • 98
  • 3
    Clever, but what if there are 2 or more KeyValue objects containing the same value? Which key should one choose? – Vineet Reynolds Sep 05 '09 at 18:15
  • 2
    @Vineet, I don't see how this approach solves the OP's question. what did you mean by "Then when you have a value, you also have the key."? – Qiang Li Sep 04 '11 at 16:53
12

I think this is best solution, original address: 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;
          }
        }

An easy usage: if you put all data in hasMap and you have item = "Automobile", so you are looking its key in hashMap. that is good solution.

getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
RevanthKrishnaKumar V.
  • 1,855
  • 1
  • 21
  • 34
boy
  • 187
  • 1
  • 9
9

I'm afraid you'll just have to iterate your map. Shortest I could come up with:

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();
    }
}
André van Toly
  • 545
  • 3
  • 9
9
for(int key: hm.keySet()) {
    if(hm.get(key).equals(value)) {
        System.out.println(key); 
    }
}
josliber
  • 43,891
  • 12
  • 98
  • 133
Ashwin
  • 101
  • 1
  • 2
7

It sounds like the best way is for you to iterate over entries using map.entrySet() since map.containsValue() probably does this anyway.

RevanthKrishnaKumar V.
  • 1,855
  • 1
  • 21
  • 34
Jonas K
  • 4,215
  • 2
  • 24
  • 25
  • Yes, that's exactly what it does. But of course it returns true as soon as it finds one value for which .equals is true, as opposed to what OP will probably need to do. – CPerkins Sep 06 '09 at 00:08
  • 1
    Well, iterating over entries can return with key as soon as it finds a matching value too. Multiple matches did not seem to be a concern. – Jonas K Sep 06 '09 at 22:11
7

For Android development targeting API < 19, Vitalii Fedorenko one-to-one relationship solution doesn't work because Objects.equals isn't implemented. Here's a simple alternative:

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;
}
The Berga
  • 3,744
  • 2
  • 31
  • 34
  • This solution works for me; also developing for an archaeological Android version, in my case to get the key of a Google Map marker held in a Map in an "onMarkerClick" event. Iterating the entrySet works; but iterating the keys and matching them to entries with get(), and comparing the output, didn't. – Toby Wilson Dec 24 '16 at 18:02
3

You can use the below:

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);
            }
        }
    }
}
Tom
  • 16,842
  • 17
  • 45
  • 54
  • It is nice that you want to provide useful stuff, but it shouldn't be a "code only" answer and the code itself shouldn't be full of code smells, either. – Tom Nov 09 '16 at 23:17
3

I think keySet() may be well to find the keys mapping to the value, and have a better coding style than entrySet().

Ex:

Suppose you have a HashMap map, ArrayList res, a value you want to find all the key mapping to , then store keys to the res.

You can write code below:

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

rather than use entrySet() below:

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

Hope it helps :)

FrancisGeek
  • 127
  • 2
  • 9
  • 2
    `map.get(key) == value` is not a good idea when checking equality of objects, as you are comparing references. Object equality should always use their `.equals()` – frododot Nov 14 '18 at 04:10
3

Simplest utility method to fetch a key of a given value from a Map:

public static void fetchValue(Map<String, Integer> map, Integer i)
{   
Stream stream = map.entrySet().stream().filter(val-> val.getValue().equals(i)).map(Map.Entry::getKey);
stream.forEach(System.out::println);    
}

detailed explaination:

  1. Method fetchValue accepts the map, which has String as key and Integer as value.

  2. Then we use entryset().stream() to convert result into a stream.

  3. Next we use filter (intermediate operation) which gives us a value that is equal to the second argument.

  4. Finally, we use forEach(final operation) to print our end result.

Shashank Bodkhe
  • 941
  • 10
  • 15
2

Yes, you have to loop through the hashmap, unless you implement something along the lines of what these various answers suggest. Rather than fiddling with the entrySet, I'd just get the keySet(), iterate over that set, and keep the (first) key that gets you your matching value. If you need all the keys that match that value, obviously you have to do the whole thing.

As Jonas suggests, this might already be what the containsValue method is doing, so you might just skip that test all-together, and just do the iteration every time (or maybe the compiler will already eliminate the redundancy, who knows).

Also, relative to the other answers, if your reverse map looks like

Map<Value, Set<Key>>

you can deal with non-unique key->value mappings, if you need that capability (untangling them aside). That would incorporate fine into any of the solutions people suggest here using two maps.

Carl
  • 7,538
  • 1
  • 40
  • 64
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);
    }

}
margus
  • 37
  • 1
  • I think this answer could be improved by adding an explanation. – Jonathan Dec 12 '12 at 20:47
  • 2
    -1. I tested it with `String` as key and value. When I call `map.add("1", "2"); map.add("1","3");` then I can call `map.getKey("2");` and retrieve `"1"`, even though `"1"` is the key for `"3"`. – jlordo Jan 30 '13 at 10:01
  • @Jonathan the idea behind this class is to keep another HashMap with the reverse mappings so that in addition to retrieving a value from a key, you can retrieve a key from a value. The T1 & T2 classes are a bit confusing; maybe literally name them Key & Value instead? Although I would expect the ability to receive more than one value or more than one key in return, depending on the data & what you want. Use with caution – Chicowitz Oct 06 '14 at 20:54
  • 1
    @theknightwhosaysni "1" is not the key for "2" (anymore). This is also the answer to your question, calling `getValue("1")` will return `3`. – jlordo Oct 25 '14 at 11:24
  • Sorry jlordo, I was mistaken about standard Hashmap behavior: you are correct in that adding a new value for a key should replace the old value – Chicowitz Oct 27 '14 at 04:26
2

In java8

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

You can get the key using values using following code..

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);
Gray
  • 115,027
  • 24
  • 293
  • 354
Amit
  • 75
  • 1
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 map = new HashMap(); map.put("A", 1); map.put("B", 2); map.put("C", 3); map.put("D", 4); // System.out.println(map); System.out.println(getKey(map, "4")); – Amazing India Jun 22 '17 at 07:35
  • 1
    What happens if multiple keys have the same value? – Cà phê đen Jun 22 '17 at 07:45
  • When u pass the multiple keys have the same value, we will get the last key as result. example: A 1, B 1, C 1, D 2 output: if we pass the 1 value , output will be C – Amazing India Jun 22 '17 at 09:39
  • @AmazingIndia This is not guaranteed and completely depends on the specific map implementation. HashMap for instance does not guarantee an order, so you have no idea what output will be returned here. – Niels Doucet Aug 16 '17 at 08:34
2

Found too many answers. Some were really great. But I was particularly looking for a way, so that I can get the value using loops.

So here is finally what I did: For a HashMap 1-to-1 relation:

    Map<String, String> map = new HashMap<String, String>();
    
    map.put("abc", "123");
    map.put("xyz", "456");
    
    for(Entry<String, String> entry : map.entrySet()) {
        if(entry.getValue().equalsIgnoreCase("456")) {
            System.out.println(entry.getKey());
        }
    }

Output: "xyz"

For a HashMap 1-to-many relation:

    Map<String, ArrayList<String>> service = new HashMap<String, ArrayList<String>>();
    
    service.put("abc", new ArrayList<String>());
    service.get("abc").add("a");
    service.get("abc").add("b");
    service.get("abc").add("c");
    
    service.put("xyz", new ArrayList<String>());
    service.get("xyz").add("x");
    service.get("xyz").add("y");
    service.get("xyz").add("z");
    
    for(Entry<String, ArrayList<String>> entry : service.entrySet()) {
        ArrayList<String> values = entry.getValue();
        for(String value : values) {
            if(value.equalsIgnoreCase("x")) {
                System.out.println(entry.getKey());
            }
        }
        
    }

Output: xyz

-Thanks

2

Use a thin wrapper: 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;
   }
}
RevanthKrishnaKumar V.
  • 1,855
  • 1
  • 21
  • 34
Jayen
  • 5,653
  • 2
  • 44
  • 65
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);
    }
}
Ankush soni
  • 1,439
  • 1
  • 15
  • 30
Madhav
  • 19
  • 2
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
     */
}
Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
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;
}
kanaparthikiran
  • 523
  • 12
  • 15
1

My 2 cents. You can get the keys in an array and then loop through the array. This will affect performance of this code block if the map is pretty big , where in you are getting the keys in an array first which might consume some time and then you are looping. Otherwise for smaller maps it should be ok.

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)            
}
Allan Pereira
  • 2,572
  • 4
  • 21
  • 28
Manu Bhat
  • 135
  • 2
  • 8
  • And why should someone use that approach? As you already said, the performance would be worse, than in other approaches. – Tom Jul 05 '16 at 13:06
1

While this does not directly answer the question, it is related.

This way you don't need to keep creating/iterating. Just create a reverse map once and get what you need.

/**
 * 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;
}
Markymark
  • 2,804
  • 1
  • 32
  • 37
0

It's important to note that since this question, Apache Collections supports Generic BidiMaps. So a few of the top voted answers are no longer accurate on that point.

For a Serialized BidiMap that also supports duplicate values ( 1-to-many scenario ) also consider MapDB.org.

kervin
  • 11,672
  • 5
  • 42
  • 59
0
  1. If you want to get key from value, its best to use bidimap (bi-directional maps) , you can get key from value in O(1) time.

    But, the drawback with this is you can only use unique keyset and valueset.

  2. There is a data structure called Table in java, which is nothing but map of maps like

    Table< A, B , C > == map < A , map < B, C > >

    Here you can get map<B,C> by querying T.row(a);, and you can also get map<A,C> by querying T.column(b);

In your special case, insert C as some constant.

So, it like < a1, b1, 1 > < a2, b2 , 1 > , ...

So, if you find via T.row(a1) ---> returns map of --> get keyset this returned map.

If you need to find key value then, T.column(b2) --> returns map of --> get keyset of returned map.

Advantages over the previous case :

  1. Can use multiple values.
  2. More efficient when using large data sets.
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Batman
  • 301
  • 3
  • 4
0

try this:

static String getKeyFromValue(LinkedHashMap<String, String> map,String value) {
    for (int x=0;x<map.size();x++){
        if( String.valueOf( (new ArrayList<String>(map.values())).get(x) ).equals(value))
            return String.valueOf((new ArrayList<String>(map.keySet())).get(x));
    }
    return null;
}
programmer
  • 25
  • 8
0

As far as I know keys and values of a HashMap are not mixed when you represent them as arrays:

hashmap.values().toArray()

and

hashmap.keySet().toArray()

So the following code (since java 8) should work as expected:

public Object getKeyByFirstValue(Object value) {
    int keyNumber =  Arrays.asList(hashmap.values().toArray()).indexOf(value);
    return hashmap.keySet().toArray()[keyNumber];
}

However, (WARNING!) it works 2-3 times slower than iteration.

pseusys
  • 407
  • 2
  • 5
  • 17
0

Let the value be maxValue.

Set keySet = map.keySet();

keySet.stream().filter(x->map.get(x)==maxValue).forEach(x-> System.out.println(x));
AConsumer
  • 2,461
  • 2
  • 25
  • 33
0

lambda w/o use of external libraries
can deal with multiple values for one key (in difference to the BidiMap)

public static List<String> getKeysByValue(Map<String, String> map, String value) {
  List<String> list = map.keySet().stream()
      .collect(groupingBy(k -> map.get(k))).get(value);
  return (list == null ? Collections.emptyList() : list);
}

gets a List containing the key(s) mapping value
for an 1:1 mapping the returned list is empty or contains 1 value

Kaplan
  • 2,572
  • 13
  • 14
0

let see my example

Map<String, String> mapPeopleAndCountry = new HashMap<>();
mapPeopleAndCountry.put("Matis", "Lithuania");
mapPeopleAndCountry.put("Carlos", "Honduras");
mapPeopleAndCountry.put("Teboho", "Lesotho");
mapPeopleAndCountry.put("Marielos", "Honduras");


List<String> peopleInHonduras = mapPeopleAndCountry.keySet()
    .stream()
    .filter(r -> mapPeopleAndCountry.get(r)
                .equals("Honduras"))
    .stream(Collectors.toList());

// will return ["Carlos", "Marielos"]

Note: untested, may contains typo

smftr
  • 923
  • 3
  • 17
  • 31
0

I've been developing a JavaFX application, and this is a problem that I encounter relatively frequently. The best way that I have found to get the desired result is to use a for each loop to iterate over the keys in the hash map and then use the get method of the hash map the value is contained in with the keys you are iterating through. Below is an example of a hash map that maps a String to an int.

public static void main(String[] args) {
    
        String temp = null; 
        int number = 23;
        HashMap<String, Integer> nameNum = new HashMap<String, Integer>();

        nameNum.put("Jerry", 43);
        nameNum.put("Michael", 23);

                                    
        for(String firstName : nameNum.keySet())
        {
            if(nameNum.get(firstName) == (number))
            {
                temp = firstName;
                System.out.println("This is the name: " + temp);
            }
        }

}

Running this will result in the correct name being returned. Below is the output:

This is the name: Michael
kmj15_23
  • 1
  • 1
-1
Iterator<Map.Entry<String,String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String,String> entry = iterator.next();
    if (entry.getValue().equals(value_you_look_for)) {
        String key_you_look_for = entry.getKey();
}
} 
Sreedhar GS
  • 2,694
  • 1
  • 24
  • 26
-3

You can also do that work: First : put map (key, value) Second : to update the key you need to remove expression Third : and put a new key with the oldValue

  • 2
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 28 '21 at 16:06