Map with two-dimensional key in java

2019-03-17 22:40发布

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)

标签: java hash map
7条回答
虎瘦雄心在
2楼-- · 2019-03-17 22:55

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.

查看更多
淡お忘
3楼-- · 2019-03-17 22:59

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!!)

查看更多
疯言疯语
4楼-- · 2019-03-17 23:01

Logically, you Pair (key1, key2) corresponds to something since it is the key of your map. Therefore you may consider writing your own class having K1 and K2 as parameters and overriding the hashCode() method (plus maybe other methods for more convenience). This clearly appears to be a "clean" way to solve your problem.

查看更多
Root(大扎)
5楼-- · 2019-03-17 23:02

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.

查看更多
混吃等死
6楼-- · 2019-03-17 23:12

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
查看更多
何必那么认真
7楼-- · 2019-03-17 23:18

I have used array for the key: like this

Map<Array[K1,K2], V>

查看更多
登录 后发表回答