Java 如何使用两个独立键实现映射?

Java 如何使用两个独立键实现映射?,java,dictionary,hashmap,Java,Dictionary,Hashmap,我有一个问题,这是关于创建一个地图与2个不同的关键点。不过,这些键可能是同一类型的。问题与此类似, 但它也不一样,因为不需要同时设置键。更具体地说,属性应该是 1) 其中一个键足以从映射中获取值 2) 如果设置了其中一个键,则可以在给定第一个键的情况下设置另一个键 3) 用户不必担心它使用什么键(第一个键或第二个键) 理论上是用两张地图来实现的 public MultiKeyMap<K1, K2, V> { private HashMap<K1 , V> map1;

我有一个问题,这是关于创建一个地图与2个不同的关键点。不过,这些键可能是同一类型的。问题与此类似,

但它也不一样,因为不需要同时设置键。更具体地说,属性应该是

1) 其中一个键足以从映射中获取值

2) 如果设置了其中一个键,则可以在给定第一个键的情况下设置另一个键


3) 用户不必担心它使用什么键(第一个键或第二个键)

理论上是用两张地图来实现的

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);
}
公共多键映射{
私有hashmap1;
私有hashmap2;
公共多键映射(){
map1=新的HashMap();
map2=新的HashMap();
}
公开作废认沽权证(K1、K1、V){
?
}
公共无效获取(K1,K1,V){
?
}
公开认沽期权(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))。

下面的代码实现了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));
    }

}
公共类元组{
公开决赛X X;
公共决赛;
公共元组(X,Y){
这个.x=x;
这个。y=y;
} 
} 
公共多密钥映射{
私有哈希映射;
公共多键映射(){
map=新的HashMap();
}
公共无效putByK1(K1,V){
put(新元组(k1,null),v);
}
公共无效putByK2(K2,V){
put(新元组(null,k2),v);
}
公共无效getByK1(K1 K1){
get(新元组(k1,null));
}
公共空间getByK2(K2 K2){
get(新元组(null,k2));
}
公开认沽期权(K1 K1,K2 K2,V V){
put(新元组(null,k2),v);
put(新元组(k1,null),v);
}
公共空间K1(K1 K1,K2 K2){
put(新元组(null,k2),get(k1));
}
公共空间K2(K2 K2,K1 K1){
put(新元组(k1,null),get(k2));
}
}

键上的类型安全性有多重要?如果对每种类型都有单独的
put
方法,并且类型相同,编译器将不知道调用哪个版本。如果只使用一种方法,则不能将类型限制为“
K1
K2
”但是,如果您愿意让
get
put
方法为键获取一个
对象
,或者要求用户使用双键
put
方法,那么您可以只使用一个backing 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);
    }
}
公共多键映射{
私有哈希映射;
公共多键映射(){
map=新的HashMap();
}
公共作废放置(对象键,V){
地图放置(键,v);
}
公共void get(对象键,V){
返回map.get(key);
}
公开认沽期权(K1 K1,K2 K2,V V){
如果(!map.containsKey(k1)和&!map.containsKey(k2)){
地图放置(k1,v);
图.put(k2,v);
}
}

值得注意的是,真正的方法将对象作为其键。

为什么不使用它映射?如果没有第二级键,则将值与常量/虚拟键一起放置!@stackflowd重点是我可能有两种不同的类型,但不一定。此外,您的建议使我难以访问第二个键没有k1的evel。问题是我经常可以访问其中一个键和值,如果没有,我可以访问另一个键。如果没有第一级键,那么对第一级键使用虚拟/常量,并将值放入第二个键-值对中。我不理解您提到的类型…
put(k1 k1,K2 K2,V)
当您使用此put方法时,
put(K1 K1,V V)
需要什么。如何确定应该插入哪一个映射对?规范中有一个错误:假设您有两个条目,其中一个有第一个键“foo”,另一个有第二个键“foo”。您会得到什么(“foo”)return?很抱歉,在API中指定了类型“用户不需要麻烦它使用什么密钥(第一个或第二个)”--这意味着不能有单独的
getByK1
getByK2
方法。这可能可以。我想HashMap会调用equals方法来进行此检查,对吗?所以让对象彼此相等就足够了。因此,如果
对象
也是一个字符串,我想应该在这里调用字符串的equals方法。这是典型的esafe就足够了。我现在不需要强制执行异常,因为如果我在映射中找不到值,就会立即抛出异常