1

Is there any way to get a key associated with a known value in a map? Normally you know the key and you want to get the value, but I want to do the opposite, going from value to key. Is it possible?

user658168
  • 1,215
  • 4
  • 15
  • 15
  • 1
    Make the value the key. Yeah, that's Captian Obvious speaking, but it's really the only way apart from linear search over a map - which is like trying to club someone to death with a loaded Uzi, as Larry Wall noted. –  Apr 14 '11 at 22:22
  • possible duplicate of [Java key - key map](http://stackoverflow.com/questions/1680463/java-key-key-map) and [hashmap with reverse lookup](http://stackoverflow.com/questions/1670038/does-java-have-a-hashmap-with-reverse-lookup) – BalusC Apr 14 '11 at 22:29

5 Answers5

2

Yes, you have to iterate over the values in the map and then store each key in a list:

for (Map.Entry<K,V> entry : map.entrySet()) {
  V value = entry.getValue();
  if (value.equals(someTargetValue) {
      // add key (entry.getKey()) to list
  }
}

Or you could use a bidirectional map, though do note:

This map enforces the restriction that there is a 1:1 relation between keys and values, meaning that multiple keys cannot map to the same value.

Daniel DiPaolo
  • 55,313
  • 14
  • 116
  • 115
  • 4
    Bi-directional maps should work. If you don't want to use the extra library just do 2 maps with value-keys reversed, which is how bidirectional maps are implemented anyway. – Cristian Vrabie Apr 14 '11 at 22:27
  • Bi-directional maps as you describe only apply to mathematical identities. If you have two values pointing to the same object, then the "reverse" direction must have two keys, hence not a mathematical Map. Perhaps it is a fine point, but it makes a world of difference if your data set has duplicate Values. – Edwin Buck Apr 14 '11 at 22:41
  • @Edwin that's correct, and noted on their description on the webpage: "This map enforces the restriction that there is a 1:1 relation between keys and values, meaning that multiple keys cannot map to the same value." That's also why I offered both as potential solutions. I'll put the caveat into the answer as well. – Daniel DiPaolo Apr 14 '11 at 22:55
1

Well, I am not an expert on Google Project LambdaJ, but it certainly offers a few cool alternatives.

Supposing you have a map with all the days of the month:

month.put(1,"Monday");
month.put(2,"Tuesday");
month.put(3,"Wednesday");
...

Then we could easily achieve what you want like this:

Set<Integer> result = with(month).retainValues(is("Friday")).keySet();

Or even a few more interesting searches like:

Set<Integer> result = with(month).retainValues(anyOf(is("Monday"),is("Friday"))).keySet();
Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
0

Here they already talked about Bidirectional maps. Nowadays, Guava (https://github.com/google/guava) offers a nice BiMap that you can use for that purpose:

https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap

raspayu
  • 5,089
  • 5
  • 37
  • 50
0

Without iterating all the keys looking for the value you can use an Apache Commons BidiMap

Mauricio
  • 5,854
  • 2
  • 28
  • 34
0

A Map is a mathematical entry which doesn't imply that a reverse mapping is possible. That said you might be able to create a "reverse" mapping if every mapped value is unique. Naturally, you'll have to encapsulate all the data manipulations in methods that update both Maps appropriately.

Map<Key, Value> normal;
Map<Value, Key> reverse;

If every mapped value is not unique, then you need to create a reverse mapping of a value to a list of keys.

Map<Key, Value> normal;
Map<Value, List<Key>> reverse;

Finally, if you don't care about fast access, you can iterate over the entire Map looking for Values. Since you'll need both the Value and the Key, it is probably best to iterate over the Map.Entry items.

Value searchingFor = ...;
Map<Key, Value> normal;
List<Key> keys = new ArrayList<Key>();
for (Map.Entry<Key, Value> entry : normal.entrySet()) {
   if (entry.getValue().equals(searchingFor)) {
     keys.add(entry.getKey());
   }
}

The technique you choose to use will depend heavily on whether it is better to trade speed for memory footprint. Generally having an extra Map is faster due to the hashing being done on the Value(s), but costs extra memory. Having a loop over the Map.Entry(s) is slower, but costs less memory.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138