Две карты. Одна карта
и одна карта
. Если у вас должен быть один интерфейс, напишите класс-оболочку, который реализует указанные методы.
See Google Collections. Or, as you suggest, use a map internally, and have that map use a Pair. You'll have to write or find Pair<>; it's pretty easy but not part of the standard Collections.
Похоже, ваше решение вполне вероятно для этой цели, честно говоря, я не вижу проблемы с ним, если ваши два ключевых типа действительно различны. Просто заставляет вас писать свою собственную реализацию для этого и решать проблемы синхронизации, если это необходимо.
Если вы собираетесь использовать комбинацию нескольких клавиш в качестве одной, то, возможно, apache commnons MultiKey - ваш друг. Я не думаю, что это будет работать один за другим, хотя ..
Define a class that has an instance of K1 and K2. Then use that as class as your key type.
Звучит как кортеж Python. Следуя этому духу, вы можете создать собственный неизменный класс, который реализует Comparable, и вы его получите.
Я вижу следующие подходы:
a) Используйте 2 разные карты. Вы можете обернуть их в класс, как вы предлагаете, но даже это может быть излишним. Просто используйте карты непосредственно: Во многих общих случаях пробел key1
и пробел key2
не пересекаются. В этом случае вам не нужно делать ничего особенного. Просто определите карту, в которой есть записи key1 => v
, а также key2 => v
Предложение, предложенное некоторыми ответчиками:
public interface IDualMap<K1, K2, V> {
/**
* @return Unmodifiable version of underlying map1
*/
Map<K1, V> getMap1();
/**
* @return Unmodifiable version of underlying map2
*/
Map<K2, V> getMap2();
void put(K1 key1, K2 key2, V value);
}
public final class DualMap<K1, K2, V>
implements IDualMap<K1, K2, V> {
private final Map<K1, V> map1 = new HashMap<K1, V>();
private final Map<K2, V> map2 = new HashMap<K2, V>();
@Override
public Map<K1, V> getMap1() {
return Collections.unmodifiableMap(map1);
}
@Override
public Map<K2, V> getMap2() {
return Collections.unmodifiableMap(map2);
}
@Override
public void put(K1 key1, K2 key2, V value) {
map1.put(key1, value);
map2.put(key2, value);
}
}
Мне кажется, что методы, которые вы хотите задать в своем вопросе, поддерживаются непосредственно Map. Кажется, вам нужны
put(K1 key, K2 key, V value)
put(K1 key, V value)
put(K2 key, V value)
. Обратите внимание, что в map, get ()
и containsKey ()
и т. Д. Все принимают Object
аргументы. , Ничто не мешает вам использовать один метод get ()
для делегирования всем составным картам, которые вы объединяете (как указано в вашем вопросе и других ответах). Возможно, вам понадобится регистрация типа, чтобы не возникло проблем с приведением классов (если они специальные + наивно реализованы.
Типизированная регистрация также позволит вам получить "правильную" карту, которая будет использоваться:
Map<T,V> getMapForKey(Class<T> keyClass){
//Completely naive implementation - you actually need to
//iterate through the keys of the maps, and see if the keyClass argument
//is a sub-class of the defined map type. And then ordering matters with
//classes that implement multiple interfaces...
Map<T,V> specificTypeMap = (Map<T,V) maps.get(keyClass);
if (specificTypeMap == null){
throw new IllegalArgumentException("There is no map keyed by class" + keyClass);
}
return maps.get(keyClass);
}
V put(Object key, V value) {
//This bit requires generic suppression magic - but
//nothing leaves this class and you're testing it right?
//(You can assert that it *is* type-safe)
Map map = getMapForKey(key.getClass());
map.put(object, key);
}
void put(Object[] keys, V value) { //Or put(V value, Object ... keys)
//Might want to catch exceptions for unsupported keys and log instead?
.....
}
] Просто идеи ...
Я все еще собираюсь предложить решение с двумя картами, но с помощью твиста
Map<K2, K1> m2;
Map<K1, V> m1;
Эта схема позволяет вам иметь произвольное количество ключевых «псевдонимов».
Она также позволяет вам обновлять значение через любой ключ без рассинхронизации карт.
В зависимости от того, как он будет использоваться, вы можете сделать это с двумя картами Map
и Map
или с двумя картами Map
и Map
. Если один из ключей более постоянный, чем другой, второй вариант может иметь больше смысла.
Commons-collections предоставляет именно то, что вы ищете: https://commons.apache.org/proper/commons-collections/apidocs/
Похоже, сейчас общие коллекции напечатаны.
Типизированную версию можно найти по адресу: https://github.com/megamattron/collections-generic
Это точно соответствует вашему варианту использования:
MultiKeyMap<k1,k2,...,kn,v> multiMap = ??
Почему бы просто не отказаться от требования, что ключ должен быть определенного типа, т.е. просто использовать Map
Иногда дженерики просто не стоят дополнительной работы.