I'm looking for an implementation of java.util.Map that has a method that will return all they keys mapped to a given value, that is, there are multiple keys map to the same value. I've looked at Google Collections and Apache Commons and didn't notice anything. Of course, I could iterate through the keyset and check each corresponding value or use two maps, but I was hoping there was something available already built.
I don't know if that solution is good for you, but you can implement easily that by using a standard map from keys to values and a MultiMap from values to key.
Of course you'll have to take care of the syncronization of the two structures, IE when you remove a key from the map, you have to remove the key itself from the set of keys mapped to the value in the multimap.
It doesn't seems difficult to implement, maybe a bit heavy from the memory overhead aspect.
What you're looking for here is a bidirectional map, for which there is an implementation in commons collections.
Your value objects could have a property (of type ArrayList maybe) that holds all the keys.
Then you extend HashMap (or whatever Map impl you use) and override put so that when you put and object for a key you also add the key to your object's list of keys.
I can't find a ready made class that supports values with multiple keys. However you could re-implement the Apache Commons DualHashBidiMap using a MultiHashMap in place of one of the HashMaps.
Related
I'm reviewing the capabilities of Googles Guava API and I ran into a data structure that I haven't seen used in my 'real world programming' experience, namely, the BiMap. Is the only benefit of this construct the ability to quickly retrieve a key, for a given value? Are there any problems where the solution is best expressed using a BiMap?
Any time you want to be able to do a reverse lookup without having to populate two maps. For instance a phone directory where you would like to lookup the phone number by name, but would also like to do a reverse lookup to get the name from the number.
Louis mentioned the memory savings possible in a BiMap implementation. That's the only thing that you can't get by wrapping two Map instances. Still, if you let us wrap the Map instances for you, we can take care of a few edges cases. (You could handle all these yourself, but why bother? :))
If you call put(newKey, existingValue), we'll error out immediately to keep the two maps in sync, rather than adding the entry to one map before realizing that it conflicts with an existing mapping in the other. (We provide forcePut if you do want to override the existing value.) We provide similar safeguards for inserting null or other invalid values.
BiMap views keep the two maps in sync: If you remove an element from the entrySet of the original BiMap, its corresponding entry is also removed from the inverse. We do the same kind of thing in Entry.setValue.
We handle serialization: A BiMap and its inverse stay "connected," and the entries are serialized only once.
We provide a smart implementation of inverse() so that foo.inverse().inverse() returns foo, rather than a wrapper of a wrapper.
We override values() to return a Set. This set is identical to what you'd get from inverse().keySet() except that it maintains the same iteration order as the original BiMap.
I have a Map having duplicate values. I now want to get the key using value without iterating through all the Map.Entries. I have more than 500 entries in the map. I do not want to iterate the whole map each time.
I thought of using BiMap of google collections. But, BiMap does not support duplicate keys. Could anyone suggest on what other thirdparty library can be used to solve this?
Update:
The map contains duplicate values and it's loaded from a text file containing key value pairs.
You could use a ListMultimap and then use Multimaps.invertFrom() to get the inverse mapping.
I have a Map
...well, there's your problem! It sounds like the data doesn't quite fit the limitations of a BiMap. Consider maintaining a different ordered collection of your data encapsulated as tuples (or a pair of ordered collections).
Given the value, I need to get the index or key which this value belongs in a Map without the need to iterate it. I'm using java.
Thanks
Guava has a BiMap, which is a bidirectional map (each key and each value are unique).
If you don't waht to use an external library, you only have 2 options:
use a plain HashMap and you will need to iterate over the keys
use 2 hashmaps, one relating keys to values, and one relating values to keys (which in essence is what a bidirectional map does).
You could always use a BidiMap from commons-collections:
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/BidiMap.html
You have to use some kind of BidirectionalMap. For example this one: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/BiMap.html
You can't without iterating.
Also, the value could belong to multiple keys, so your question is somewhat moot.
If there was a one-to-one relationship between the keys/values, you could do it by having two maps - one for each direction of the relationship - and looking up the value as a key of the second (reverse) map.
I have input as a values. I need to retrieve key of that values in hashtable.
Please help to me sort out this. Appreciate your help.
Basically that's not how a hash table works - you're expected to look up by key. You can iterate over all the entries and find the - potentially multiple - keys which map to the particular value, but it won't be fast.
Instead, you should consider using a bidirectional map (bimap) such as the ones provided by Guava, assuming your situation really calls for a single-key-to-single-value solution. (There are lots of options around collections in Guava; if you give us more information about your situation, we may be able to help more.)
What you are looking for is a BiMap data structure. Google's guava provides an implementation of it. BidiMap interface in Commons Collections.
JAXB doesn't let you unmarshal already existing xml structures into HashMaps if they are not exactly the way JAXB expects them.
JAXB is fine with handling e.g. LinkedLists and filling them.
I was thinking of creating a interface with a getKey() method and a wrapper around the HashMap taking all objects that implement that interface. The wrapper can then use the getKey() method for all key related features of the map. The wrapper could then easily implement the Collection or List interface.
Because this idea doesn't seem to innovative to me I presume that it already exists in some package, but I'm not googling correctly for it... Can someone please name a good lib that can do this, or do I have to code this myself?
You might consider extending ForwardingList of guava, and using a HashMap in the back. I don't know of any implementation that will leave you only the actual mapping.
Another alternative is creating JAXB XmlAdapter to adapt the values to your map. I think this one is more appropriate.
If all you are trying to pass the information content of a Map as a Collection, use Map.entrySet(). That gives you a Set<Map.EntrySet<K,V>> object; i.e. a collection whose elements are the key/value pairs of the Map. To reconstruct a Map from the collection, you will need to iterate the set and perform an put for each element.