我遇到的问题是创建一个包含2个不同键的地图。键虽然可能是相同的类型。问题类似于此,
How to create a map with 2 key value
但它也有所不同,因为不需要同时设置键。更具体地说,属性应该是,
1)其中一个键足以从地图中获取值。
2)如果设置了其中一个键,则可以在给定第一个键的情况下设置另一个键。
3)用户不需要打扰它使用的密钥(第一个或第二个)
理论是使用2个地图来实现这个,
public MultiKeyMap<K1, K2, V> {
private HashMap<K1 , V> map1;
private HashMap<K2, V> map2;
public MultiKeyMap(){
map1 = new HashMap<K1, V>();
map2 = new HashMap<K2, V>();
}
public void put(K1 k1, V v){
?
}
public void get(K1 k1, V v){
?
}
public void put(K1 k1, K2 k2, V v){
map1.put(k1, v);
map2.put(k2, v);
}
然而,当我到达具有一个值的部分时,我感到困惑,键可能都是相同的类型(例如字符串),所以我如何在值之间产生差异。一种替代方案是,如果第二个值与第一个值的类型相同,那么我只需使用重复值将其添加到第一个地图。这是一个不错的选择吗?我的观点是,这会影响语法,因为用户仍然只会调用myMap.get(myKey)
,此外,我还猜测这将是一个优化,因为我只需要一个地图。我只需要一个像boolean secondKeyAvail = false
这样的旗帜。我应该能够自己处理(2)。这更多的是给出背景并激发为什么这个问题与链接的问题不同。
修改
由于一些评论,我将尝试澄清一下。这就是场景。 在我需要阅读地图之前,我将遇到一个键(总是相同的键)。但是,在我需要阅读地图时,有时可能无法访问此关键对象。然后我将有一个未添加到地图的默认值。但是,在这种情况下,我将有第二个键,如果发生这种情况,我将能够使用第一个键设置第二个键。但是,如果键是相同的类型,我将不知道我是否有K1键或带有调用的K2键(myMap.get(myKey))。
答案 0 :(得分:1)
键上的类型安全有多重要?如果每种类型都有单独的put
方法,然后类型相同,则编译器将不知道要调用哪个版本。如果您只使用一种方法,则不能将类型限制为“K1
或K2
”。但是,如果您愿意使用get
和put
方法获取密钥的Object
,或者要求用户使用双键put
方法,那么您可以使用单个支持HashMap,它不关心密钥类型是什么。
public MultiKeyMap<K1, K2, V> {
private HashMap<Object, V> map;
public MultiKeyMap(){
map = new HashMap<Object, V>();
}
public void put(Object key, V v){
map.put(key, v);
}
public void get(Object key, V v){
return map.get(key);
}
public void put(K1 k1, K2 k2, V v){
if(!map.containsKey(k1) && !map.containsKey(k2)) {
map.put(k1, v);
map.put(k2, v);
}
}
值得注意的是,真正的HashMap.get()
方法无论如何都需要Object
。
答案 1 :(得分:0)
以下代码实现了API,允许您通过K1或K2输入值,以通过任何键获取值并将一个键传播到另一个键
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
public MultiKeyMap<K1, K2, V> {
private HashMap<Tuple<K1, K2> , V> map;
public MultiKeyMap(){
map = new HashMap<Tuple<K1, K2>, V>();
}
public void putByK1(K1 k1, V v){
map.put(new Tuple(k1, null), v);
}
public void putByK2(K2 k2, V v){
map.put(new Tuple(null, k2), v);
}
public void getByK1(K1 k1){
map.get(new Tuple(k1, null));
}
public void getByK2(K2 k2){
map.get(new Tuple(null, k2));
}
public void put(K1 k1, K2 k2, V v){
map.put(new Tuple(null, k2), v);
map.put(new Tuple(k1, null), v);
}
public void propagateK1(K1 k1, K2 k2) {
map.put(new Tuple(null, k2), get(k1));
}
public void propagateK2(K2 k2, K1 k1) {
map.put(new Tuple(k1, null), get(k2));
}
}