Map with two-dimensional key in java
Solution 1
You should use Map<Pair<K1,K2>, V>
It will only contain one map, instead of N+1 maps
Key construction will be obvious (creation of the Pair)
Nobody will get confused as to the meaning of the Map as its programmer facing API won't have changed.
Dwell time in the data structure would be shorter, which is good if you find you need to synchronize it later.
Solution 2
If you're willing to bring in a new library (which I recommend), take a look at Table in Guava. This essentially does exactly what you're looking for, also possibly adding some functionality where you may want all of the entries that match one of your two keys.
interface Table<R,C,V>
A collection that associates an ordered pair of keys, called a row key and a column key, with a single value. A table may be sparse, with only a small fraction of row key / column key pairs possessing a corresponding value.
Solution 3
While I also am on board with what you proposed (a pair of values to use as the key), you could also consider making a wrapper which can hold/match both keys. This might get somewhat confusing since you would need to override the equals and hashCode methods and make that work, but it could be a straightforward way of indicating to the next person using your code that the key must be of a special type.
Searching a little bit, I found this post which may be of use to you. In particular, out of the Apache Commons Collection, MultiKeyMap. I've never used this before, but it looks like a decent solution and may be worth exploring.
Solution 4
I'd recommend going for the second option
Map<Pair<K1,K2>,V>
The first one will generate more overload when retrieving data, and even more when inserting/removing data from the Map. Every time that you put a new Value V, you'll need to check if the Map for K1 exists, if not create it and put it inside the main Map, and then put the value with K2.
If you want to have an interface as you're exposing initially wrap your Map<Pair<K1,K2>,V>
with your own "DoubleKeyMap".
(And don't forget to properly implement the methods hash and equals in the Pair class!!)
Solution 5
I would opt for the Map<Pair<K1,K2>, V>
solution, because:
- it directly expresses what you want to do
- is potentially faster because it uses fewer indirections
- simplifies the client code (the code that uses the
Map
afterwards
Related videos on Youtube
EclipseQuestion
Updated on July 09, 2022Comments
-
EclipseQuestion almost 2 years
I want a map indexed by two keys (a map in which you put AND retrieve values using two keys) in Java. Just to be clear, I'm looking for the following behavior:
map.put(key1, key2, value); map.get(key1, key2); // returns value map.get(key2, key1); // returns null map.get(key1, key1); // returns null
What's the best way to to it? More specifically, should I use:
Map<K1,Map<K2,V>>
Map<Pair<K1,K2>, V>
Other?
(where K1,K2,V are the types of first key, second key and value respectively)
-
Adrian Mouat about 13 yearsCan't you just have one key made up of two values?
-
JAB about 13 years@Adrian: Isn't that what
Map<Pair<K1,K2>, V>
would do? There's technically only one key, but it consists of two values. -
EclipseQuestion about 13 years@Adrian Yes, that was what I meant with the second choice
-
EclipseQuestion about 13 yearsI'm using 'apache commons' lib. Does anyone know if the 'Pair' class will work? (I mean, if it implements hashCode and equals correctly FOR THIS CASE?)
-
Edwin Buck about 13 yearsHashes need not be perfect, a good way is to implement your own pair. The
hashcode()
method can just return a.hashCode() xor b.hashCode(). -
Marcelo about 13 yearsYes, and you can use the
HashBasedTable<R,C,V>
implementation guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/… -
Pedro Borges over 10 yearsBut doesn't that just alloc memory for a pair object EVERY time we search for something in the doubleMap? I mean, it's cleaner and all, but what if we're talking a big map with static data, isn't this solution badly engineered memory wise?
-
Edwin Buck over 10 yearsIf you are worried about allocating each time you search, it doesn't really matter what kind of Map you use because the Map isn't really the core issue. You would probably want a Factory to generate the Key backed to a store of unique keys, such that two requests to generate two keys return the same object twice. It's independent of the Map of pair issue, and a Map of Maps is likely to take more storage anyway, considering the hash array (1 vs 1*M, in a M*N example) and bucket lists they both will have to maintain.
-
Henno Vermeulen about 9 yearsInterestingly, this uses the Map<K1,Map<K2,V>> approach internally.