如何使用2个独立键实现地图?

时间:2015-09-22 14:32:53

标签: java dictionary hashmap

我遇到的问题是创建一个包含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))。

2 个答案:

答案 0 :(得分:1)

键上的类型安全有多重要?如果每种类型都有单独的put方法,然后类型相同,则编译器将不知道要调用哪个版本。如果您只使用一种方法,则不能将类型限制为“K1K2”。但是,如果您愿意使用getput方法获取密钥的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));
    }

}