简体   繁体   中英

Why is there no method for returning a Key given a Value in a Java Map?

In the Javadocs , the Map interface has methods for containsKey(Object key) , containsValue(Object value) , and get(Object key) . Why is there then no method getKey(Object value) ? Once you have a method to find whether the Map contains the Value, why can't you also return it?
I understand it's possible for the Map to contain more than one of any Value, but perhaps the method could return the first instance of the value.

Let's use an implementation of java.util.Map in the same way you'd use a contacts list, either at your job or one you keep on your phone.

Let's say, for instance, you want to find your friend John Smith's phone number so you can give him a call. You are given the chance to search either by first name or by last name.

However, Java's limitation on maps is that the key must be unique across all keys, and thus, if you know a John Smith and a John Doe, then the last person you inserted into the map will "win", and you'll lose the data of John Smith. Silently.

If you instead inserted by last name (eg Smith), and were to then put values of all of the Smiths you knew into a list (John, Jane, William, Robert, Emmett), you would be able to find what you were looking for both efficiently and safely, without the risk of damaging your contact list.


The reason that you can't search by value is that a value has no explicit guarantee of uniqueness when stored in a key-value pair data structure . Even Guava's BiMap , which has been touted as a "solution" to your problem, still suffers from the limitation of uniqueness across keys and values, which ain't what you want. Worse still, it would be a nightmare to have a structure of Map<List<String>, String> , chiefly because that key can change which is not what anyone wants at all .

If you want to be able to get a key given a value, then you have no choice but to iterate the entire contents of the data structure, which (thankfully, or frightfully - take your pick) is exactly what Map.Entry<K, V> provides - an iterable entry set so that you can do your own checks on each element in the map.

The Java Map interface is designed for efficient lookup of values by key.

One of the most common implementations used is a HashMap , which puts the values into buckets and provides constant-time lookup (assuming the values are well-distributed in the buckets). This means that looking up a key is extremely fast - you can hash the key in constant time and almost immediately see if there is a matching value. However, in order to check for the presence of a value, you need to iterate through all of the values.

Another common implementation is the TreeMap , which can be better than the HashMap in some cases where your keys can be easily sorted. The branches of the tree allow for quick (though log(n) , not constant-time) lookup of the keys. However, once again, looking up the values requires traversing every node of the tree until a value is found.

If you need this kind of lookup that can go from Key to Value or Value to Key, you should be using a BiMap , which is basically two maps rolled into one object - one forward map and one reverse map. Google's Guava library has one that I have used in the past.


The better question would be "why does the Java Map interface provide a containsValue method if this method will be inefficient for most implementations?" but I expect that is probably off-topic for SO - you might consider asking it at Computer Science .

The Java collections framework does not implement every feature that could theoretically be actualized with the classes provided -- some features may need to be added in a specific application. There's no knock-down right answer to why one set of features was chosen over another -- only the original designers of the framework know that.

In this case, though, it seems plausible to conjecture that providing a reverse (value->key) lookup would be a bad idea for at least two reasons. First, it wouldn't be obvious to developers that it would necessarily be inefficient compared to the forward (key->value) lookup. It would become obvious pretty quickly if you actually have to implement it using iteration.

Second, although the OP says that the reverse lookup method might return the "first" matching value in the case where multiple keys map to the same value, there really isn't a robust notion of "first" in a map.

In the end, though, it's all speculation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM