我认为你可以通过以下两个课程达到你所需要的。虽然它涉及两张地图,但它们不会暴露在外部世界中,因此不应该有一种方法让它们失去同步。至于将相同的“事实”存储两次,我认为在任何有效的实现中都不会绕过这一点,不管事实是显式存储的两次,还是隐式存储的,就像在数据库创建索引以提高两个表上的联接效率时那样。您可以向magicSet添加新内容,它将更新两个映射,或者您可以向magicMapper添加内容,然后magicMapper将自动更新反向映射。女朋友现在叫我睡觉,所以我不能通过编译器来运行这个程序——这应该足够让你开始了。你想解决什么难题?
public class MagicSet {
private Map forward;
private R r;
private Set set;
public MagicSet(Map forward, R r) {
this.forward = map;
this.r = r;
this.set = new HashSet();
}
public void add(L l) {
set.add(l);
forward.put(l,r);
}
public void remove(L l) {
set.remove(l);
forward.remove(l);
}
public int size() {
return set.size();
}
public in contains(L l){
return set.contains(l);
}
// caution, do not use the remove method from this iterator. if this class was going
// to be reused often you would want to return a wrapped iterator that handled the remove method properly. In fact, if you did that, i think you could then extend AbstractSet and MagicSet would then fully implement java.util.Set.
public Iterator iterator() {
return set.iterator();
}
}
public class MagicMapper { // note that it doesn't implement Map, though it could with some extra work. I don't get the impression you need that though.
private Map forward;
private Map> inverse;
public MagicMapper() {
forward = new HashMap;
inverse = new HashMap>;
}
public R getForward(L key) {
return forward.get(key);
}
public Set getBackward(R key) {
return inverse.get(key); // this assumes you want a null if
// you try to use a key that has no mapping. otherwise you'd return a blank MagicSet
}
public void put (L l, R r) {
R oldVal = forward.get(l);
// if the L had already belonged to an R, we need to undo that mapping
MagicSet oldSet = inverse.get(oldVal);
if (oldSet != null) {oldSet.remove(l);}
// now get the set the R belongs to, and add it.
MagicSet newSet = inverse.get(l);
if (newSet == null) {
newSet = new MagicSet(forward, r);
inverse.put(r,newSet);
}
newSet.add(l); // magically updates the "forward" map
}
}