Two maps. One Map<K1, V>
and one Map<K2, V>
. If you must have a single interface, write a wrapper class that implements said methods.
Commons-collections provides just what you are looking for: https://commons.apache.org/proper/commons-collections/apidocs/
Looks like now the commons-collections is typed.
A typed version can be found at: https://github.com/megamattron/collections-generic
This will exactly support your use case:
MultiKeyMap<k1,k2,...,kn,v> multiMap = ??
I'm still going suggest the 2 map solution, but with a tweest
Map<K2, K1> m2;
Map<K1, V> m1;
This scheme lets you have an arbitrary number of key "aliases".
It also lets you update the value through any key without the maps getting out of sync.
Yet another solution is to use Google's Guava
import com.google.common.collect.Table;
import com.google.common.collect.HashBasedTable;
Table<String, String, Integer> table = HashBasedTable.create();
The usage is really simple:
String row = "a";
String column = "b";
int value = 1;
if (!table.contains(row, column)) {
table.put(row, column, value);
}
System.out.println("value = " + table.get(row, column));
The method HashBasedTable.create()
is basically doing something like this:
Table<String, String, Integer> table = Tables.newCustomTable(
Maps.<String, Map<String, Integer>>newHashMap(),
new Supplier<Map<String, Integer>>() {
public Map<String, Integer> get() {
return Maps.newHashMap();
}
});
if you're trying to create some custom maps, you should go for the second option (as @Karatheodory suggests) otherwise you should be fine with the first one.
What about you declare the following "Key" class:
public class Key {
public Object key1, key2, ..., keyN;
public Key(Object key1, Object key2, ..., Object keyN) {
this.key1 = key1;
this.key2 = key2;
...
this.keyN = keyN;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Key))
return false;
Key ref = (Key) obj;
return this.key1.equals(ref.key1) &&
this.key2.equals(ref.key2) &&
...
this.keyN.equals(ref.keyN)
}
@Override
public int hashCode() {
return key1.hashCode() ^ key2.hashCode() ^
... ^ keyN.hashCode();
}
}
Declaring the Map
Map<Key, Double> map = new HashMap<Key,Double>();
Declaring the key object
Key key = new Key(key1, key2, ..., keyN)
Filling the map
map.put(key, new Double(0))
Getting the object from the map
Double result = map.get(key);
Proposal, as suggested by some answerers:
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);
}
}
Why not just drop the requirement that the key has to be a specific type, i.e. just use Map<Object,V>.
Sometimes generics just isn't worth the extra work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With