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.
Related
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).
i need to store non unique key value pair like in an application which can only be compiled with java 1.4. It should look like :
{"key1"=>"value1",
"key2"=>"value2",
"key3"=>"value3",
"key3"=>"value4"
}
thanks in advance
In core java, I think you are stuck with storing arrays or lists as the values of a Map interface (hashmap). You might also consider answers here: Map implementation with duplicate keys
What are the semantics of asking for a duplicate key?
Here is a tricky data structure and data organization case.
I have an application that reads data from large files and produces objects of various types (e.g., Boolean, Integer, String) that are categorized in a few (less than a dozen) groups and then stored in a database.
Each object is currently stored in a single HashMap<String, Object> data structure. Each such HashMap corresponds to a single category (group). Each database record is built from the information in all the objects contained in all categories (HashMap data structures).
A requirement has appeared for checking whether subsequent records are "equivalent" in the number and type of columns, where equivalence must be verified across all maps by comparing the name (HashMap key) and the type (actual class) of each stored object.
I am looking for an efficient way of implementing this functionality, while maintaining the original object categorization, because listing objects by category in the fastest possible way is also a requirement.
An idea would be to just sort the keys (e.g., by replacing each HashMap with a TreeMap) and then walk over all maps. An alternative would be to just copy everything in a TreeMap for comparison purposes only.
What would be the most efficient way of implementing this functionality?
Also, if how would you go about finding the difference (i.e., the fields added and those removed), between successive records?
Create a meta SortedSet in which you store all the created maps.
Means SortedSet<Map<String,Object>> e.g. a TreeSet which as a custom Comparator<Map<String,Object>> which does check exactly your requirements of same number and names of keys and same object type per value.
You can then use the contains() method of this meta set structure to find out if a similar record does already exist.
==== EDIT ====
Since I've misundertood the relation between database records and the maps in the first place, I've to change some semantics my answer now of course a little bit.
Still I'would use the mentioned SortedSet<Map<String,Object>> but of course the Map<String,Object> would now point to that Map you and havexy suggested.
On the other hand could it be a step forward to use a Set<Set<KeyAndType>> or SortedSet<Set<KeyAndType>> where your KeyAndType will only contain the key and the type with appropriate Comparable implementation or equals with hashcode.
Why? You asked how to find the differences between two records? If each record relates to one of those inner Set<KeyAndType> you can easily use retainAll() to form the intersection of two successive Sets.
If you would compare this to the idea of a SortedSet<Map<String,Object>>, in both ways you would have the logic which differenciates between the fields within the comparator, one time comparing inner sets, one time comparing inner maps. And since this information gets lost when the surrounding set is constructed, it will be hard to get the differences between two records later on, if you do not have another reduced structure which is easy to use to find such differences. And since such a Set<KeyAndType> could act as key as well as as easy base for comparison between two records, it could be a good candidate to be used for both purposes.
If furthermore you wanna keep the relation between such a Set<KeyAndType> to your record or the group of Map<String,Object> your meta structure could be something like:
Map<Set<KeyAndType>,DatabaseRecord> or Map<Set<KeyAndType>,GroupOfMaps> implemented by a simple LinkedHashMap which allows simple iteration in original order.
One soln is to keep both category based HashMap and combined TreeMap. This will have slight more memory requirement, not much though, as you ll just keep the same reference in both of them.
So whenever you are adding/removing to HashMap you will do the same operation in the TreeMap too. This way both will always be in sync.
You can then use TreeMap for comparison, whether you want comparison of type of object or actual content comparison.
I want to know if BasicNameValuePair allows duplicate keys?
You can only put one key and value in an BasicNameValuePair. So you can't have duplicate keys! Or do you mean if you could have two of them with the same key? Then the answer is yes.
BasicNameValuePair is just a simple wrapper around two Strings (a name and a value). There's no way of adding more than that, so duplicate keys doesn't really make sense. There are no keys, as such, just a single name.
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.