This example shows how to get the HashMap key from the value. The example also shows how to get all keys using the value in case the value is mapped to multiple keys of the HashMap object.
How to get key using the value of the HashMap?
The HashMap class is a map implementation that maps keys with values. If you want to get HashMap value using a key, you can use the get
method and provide the key for which you want to fetch the value. But what if you want to get key from a value?
The HashMap class does not provide any direct method to get a key from value because it is not built for that purpose. However, there are several ways using which you can do that as given below.
1. Using the keySet method and a for loop (1:1 relationship)
This approach gets all the keys using the HashMap keySet method and iterates over them. If the value mapped to any key is matching with the value for which we want to get the key, it returns the key.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import java.util.HashMap; import java.util.Map; import java.util.Set; public class HashMapGetKeyFromValueExample { public static void main(String[] args) { //create new HashMap HashMap<Integer, String> hMapNumbers = new HashMap<Integer, String>(); //add key-value pairs hMapNumbers.put(1, "One"); hMapNumbers.put(2, "Two"); hMapNumbers.put(3, "Three"); System.out.println( "Key for value Two: " + getKeyFromValue(hMapNumbers, "Two") ); } private static <K, V> K getKeyFromValue(Map<K, V> map, Object value) { //get all map keys using keySet method Set<K> keys = map.keySet(); //iterate all keys for(K key : keys){ //if maps value for the current key matches, return the key if( map.get(key).equals(value) ){ return key; } } //if no values matches, return null return null; } } |
Output
1 |
Key for value Two: 2 |
2. Using the entrySet method and a for loop (1:1 relationship)
This approach is similar to the above given approach, but instead of the keys, it fetches the HashMap entries using the entrySet
method. You can also use an Iterator instead of the for loop.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.util.HashMap; import java.util.Map; public class HashMapGetKeyFromValueExample { public static void main(String[] args) { //create new HashMap HashMap<Integer, String> hMapNumbers = new HashMap<Integer, String>(); //add key-value pairs hMapNumbers.put(1, "One"); hMapNumbers.put(2, "Two"); hMapNumbers.put(3, "Three"); System.out.println( "Key for value Two: " + getKeyFromValue(hMapNumbers, "Two") ); } private static <K, V> K getKeyFromValue(Map<K, V> map, Object value) { //get map entries and iterate over them for(Map.Entry<K, V> entry : map.entrySet()){ if( entry.getValue().equals(value) ){ return entry.getKey(); } } return null; } } |
Output
1 |
Key for value Two: 2 |
3. Using a custom HashMap class (1:1 relationship)
The above two approaches use the built-in methods of the HashMap class to get the HashMap key from the value. This approach creates a custom class that extends the HashMap class having a separate map object which maintains the value to key mappings. It also defines a method to get a key from value as given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import java.util.HashMap; import java.util.Map; public class HashMapGetKeyFromValueExample { public static void main(String[] args) { //create new object of MyHashMap MyHashMap<Integer, String> myMapNumbers = new MyHashMap<Integer, String>(); //add key-value pairs myMapNumbers.put(1, "One"); myMapNumbers.put(2, "Two"); myMapNumbers.put(3, "Three"); System.out.println( "Key for value Two: " + myMapNumbers.getKeyFromValue("Two") ); } } class MyHashMap<K, V> extends HashMap<K, V>{ private static final long serialVersionUID = 1L; //this map will hold reverse mapping i.e. value to key Map<V, K> mapReverse = new HashMap<V, K>(); /* * When we put key=>value to the map, we also * want to put value=>key to the reverse map */ public V put(K key, V value) { //put value=>key in the reverse map mapReverse.put(value, key); //call put method of the HashMap return super.put(key, value); } /* * Custom method to fetch the key using a value * from the reverse map */ public K getKeyFromValue(V value){ return mapReverse.get(value); } } |
Output
1 |
Key for value Two: 2 |
What about HashMap having the same values mapped to multiple keys?
All the above example works for HashMap that has 1:1 relationship between keys and values. However, the HashMap class allows the same value being mapped to multiple keys. If that is the case, you can use the below given method to get a list of all keys mapped to a particular value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class HashMapGetKeyFromValueExample { public static void main(String[] args) { //create new HashMap HashMap<Integer, String> hMapNumbers = new HashMap<Integer, String>(); //add key-value pairs hMapNumbers.put(1, "One"); hMapNumbers.put(2, "Two"); hMapNumbers.put(3, "Three"); hMapNumbers.put(22, "Two"); hMapNumbers.put(222, "Two"); System.out.println( "Key for value Two: " + getKeyFromValue(hMapNumbers, "Two") ); } private static <K, V> List<K> getKeyFromValue(Map<K, V> map, Object value) { List<K> keyList = new ArrayList<K>(); //iterate over all entries of the HashMap for(Map.Entry<K, V> entry : map.entrySet()){ //if entry value matches with the given value if( entry.getValue().equals(value) ){ //add current key to the list keyList.add(entry.getKey()); } } return keyList; } } |
Output
1 |
Key for value Two: [2, 22, 222] |
If the value is mapped to multiple keys in the HashMap, the above method returns a list object containing all the keys. If the value is not mapped to any key, it returns an empty list.
The bad:
Approach 1 and 2 iterates over the HashMap object to find a key mapped to the given value. It is a slow operation in terms of performance especially if the map is large.
Approach 3 creates a custom class by extending the built-in HashMap class. But it needs double the memory because it also needs to maintain the reverse mappings of value to key. Also, removing any element from the map does not remove the corresponding mapping from the reverse map.
The bi-directional maps:
If you are already using the Apache Commons library in your project, you should use the data structure specifically built for this purpose i.e. bi-directional map implementation. As the name suggests, it maintains the mapping in both directions i.e. key to value and value to key.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; public class HashMapGetKeyFromValueExample { public static void main(String[] args) { BidiMap<Integer, String> bidiMapNumbers = new DualHashBidiMap<Integer, String>(); bidiMapNumbers.put(1, "One"); bidiMapNumbers.put(2, "Two"); bidiMapNumbers.put(3, "Three"); //get value from key System.out.println("Value for key 2: " + bidiMapNumbers.get(2) ); //get key from value System.out.println("Key for value Two: " + bidiMapNumbers.getKey("Two") ); } } |
Output
1 2 |
Value for key 2: Two Key for value Two: 2 |
Limitations:
As with approach 3 of creating a custom class, the DualHashBidiMap class also maintains two HashMap objects to maintain bi-directional mappings.
Plus, the BidiMap does not allow many to one relationship between values and keys. In other words, it does not allow duplicate keys or values.
Note: If you are using the Google Guava library, you can use the BiMap class to achieve the same (also supports generics).
This example is a part of the Java HashMap tutorial with examples.
Please let me know your views in the comments section below