How to implement a Map with multiple keys? [duplic

2019-01-01 00:12发布

This question already has an answer here:

I need a data structure which behaves like a Map, but uses multiple (differently-typed) keys to access its values.
(Let's not be too general, let's say two keys)

Keys are guaranteed to be unique.

Something like:

MyMap<K1,K2,V> ...

With methods like:

getByKey1(K1 key)...
getByKey2(K2 key)...
containsKey1(K1 key)...
containsKey2(K2 key)...

Do you have any suggestions?

The only thing I can think of is:
Write a class which uses two Maps internally.

EDIT Some people suggest me to use a tuple, a pair, or similar as a key for Java's Map, but this would not work for me:
I have to be able, as written above, to search values by only one of the two keys specified.
Maps use hash codes of keys and check for their equality.

27条回答
ら面具成の殇う
2楼-- · 2019-01-01 01:15

I recommend something like this:

    public class MyMap {

      Map<Object, V> map = new HashMap<Object, V>();


      public V put(K1 key,V value){
        return map.put(key, value);
      }

      public V put(K2 key,V value){
        return map.put(key, value);
      }

      public V get(K1 key){    
        return map.get(key);
      }

      public V get(K2 key){    
        return map.get(key);
      }

      //Same for conatains

    }

Then you can use it like:
myMap.put(k1,value) or myMap.put(k2,value)

Advantages: It is simple, enforces type safety, and doesn't store repeated data (as the two maps solutions do, though still store duplicate values).
Drawbacks: Not generic.

查看更多
只靠听说
3楼-- · 2019-01-01 01:16

I can see the following approaches:

a) Use 2 different maps. You can wrap them in a class as you suggest, but even that might be an overkill. Just use the maps directly: key1Map.getValue(k1), key2Map.getValue(k2)

b) You can create a type-aware key class, and use that (untested).

public class Key {
  public static enum KeyType { KEY_1, KEY_2 }

  public final Object k;
  public final KeyType t;

  public Key(Object k, KeyType t) {
    this.k = k;
    this.t= t;
  }

  public boolean equals(Object obj) {
    KeyType kt = (KeyType)obj;
    return k.equals(kt.k) && t == kt.t;
  }

  public int hashCode() {
   return k.hashCode() ^ t.hashCode();
  }
}

By the way, in a lot of common cases the space of key1 and the space of key2 do not intersect. In that case, you don't actually need to do anything special. Just define a map that has entries key1=>v as well as key2=>v

查看更多
旧时光的记忆
4楼-- · 2019-01-01 01:16

Sounds like a Python tuple. Following in that spirit, you can create an immutable class of your own devising that implements Comparable and you'll have it.

查看更多
登录 后发表回答