英文:
How can I map multiple keys to the same value in a distributed environment?
问题
在一个分布式环境中,我想讨论实现将多个键映射到同一个值的映射映射的方法。
一种实现方法(我不喜欢)(使用Java):
class ConcurrentMultiKeyMap<K1, K2, V> {
HashMap<K1, K2> map1to2 = new HashMap<>();
HashMap<K2, K1> map2to1 = new HashMap<>();
HashMap<K1, V> mapToV = new HashMap<>();
public synchronized V put(K1 k1, K2 k2, V v) {
K2 previousK2 = map1to2.get(k1);
K1 previousK1 = map2to1.get(k2);
mapToV.remove(previousK1);
map1to2.remove(previousK1);
map2to1.remove(previousK2);
map1to2.put(k1, k2);
map2to1.put(k2, k1);
return mapToV.put(k1, v);
}
// ... (其他方法的定义,省略)
@Test public void demonstration() {
// ... (演示代码,省略)
}
}
有人知道更好的解决方案吗?如果能够适用于可变数量的键并使用智能锁定方案,将会获得额外的加分。
注意:所需的解决方案需要允许分别通过任一键进行访问。因此,传统的复合键(Composite Key)无法工作,因为仅使用任一键无法计算哈希码。
提前感谢您的回答。
英文:
I'd like to discuss implementions of a map mapping multiple keys mapped to the same value in a distributed environment.
One method of implementing this(that I don't like) (in Java):
class ConcurrentMultiKeyMap<K1, K2, V> {
HashMap<K1, K2> map1to2 = new HashMap<>();
HashMap<K2, K1> map2to1 = new HashMap<>();
HashMap<K1, V> mapToV = new HashMap<>();
public synchronized V put(K1 k1, K2 k2, V v) {
K2 previousK2 = map1to2.get(k1);
K1 previousK1 = map2to1.get(k2);
mapToV.remove(previousK1);
map1to2.remove(previousK1);
map2to1.remove(previousK2);
map1to2.put(k1, k2);
map2to1.put(k2, k1);
return mapToV.put(k1, v);
}
synchronized void remove(K1 k1) {
K2 k2 = map1to2.remove(k1);
map2to1.remove(k2);
mapToV.remove(k1);
}
synchronized void remove(K2 k2) {
K1 k1 = map2to1.remove(k2);
map1to2.remove(k1);
mapToV.remove(k1);
}
synchronized V get(K1 k1) {
return mapToV.get(k1);
}
synchronized V getBy2(K2 k2) {
K1 k1 = map2to1.get(k2);
if(k1 != null)
return getBy1(k1);
else
return null;
}
public synchronized boolean containsBy1(K1 k1) {
return map1to2.containsKey(k1);
}
public synchronized boolean containsBy2(K2 k2) {
return map2to1.containsKey(k2);
}
public synchronized V[] values(V[] empty_va) {
return mapToV.values().toArray(empty_va);
}
public synchronized int size() {
return mapToV.size();
}
public synchronized boolean isEmpty() {
return mapToV.isEmpty();
}
public synchronized void clear() {
mapToV.clear();
map1to2.clear();
map2to1.clear();
}
@Override public synchronized String toString() {
StringBuilder builder = new StringBuilder();
builder.append("BadConcurrentMultiKeyMap{");
for(Map.Entry<K1, V> entry : mapToV.entrySet()) {
builder.append("(");
K1 k1 = entry.getKey();
K2 k2 = map1to2.get(k1);
V v = entry.getValue();
builder.append("k1=").append(k1).append(",");
builder.append("k2=").append(k2).append(",");
builder.append("v=").append(v);
builder.append("), ");
}
if(!isEmpty()) builder.delete(builder.length()-2, builder.length());
builder.append("}");
return builder.toString();
}
@Test public void demonstration() {
ConcurrentMultiKeyMap<Integer, String, String> map = new ConcurrentMultiKeyMap<>();
map.put(1, "1", "v1");
map.put(2, "2", "v2");
assertEquals("v1", map.getBy1(1));
assertEquals("v1", map.getBy2("1"));
assertEquals("v2", map.getBy1(2));
assertEquals("v2", map.getBy2("2"));
assertNull(map.getBy1(3));
assertNull(map.getBy2("3"));
map.removeBy1(1);
assertNull(map.getBy1(1));
assertNull(map.getBy2("1"));
map.removeBy2("2");
assertNull(map.getBy1(2));
assertNull(map.getBy2("2"));
map.put(1, "A", "v1");
System.out.println("map = " + map);
map.put(2, "A", "v2");
System.out.println("map = " + map);
map.removeBy1(1);
System.out.println("map = " + map);
System.out.println("map.mapToV = " + map.mapToV);
System.out.println("map.map1to2 = " + map.map1to2);
System.out.println("map.map2to1 = " + map.map2to1);
map.clear();
map.put(1, "A", "v1");
System.out.println("map = " + map);
map.put(2, "A", "v2");
System.out.println("map = " + map);
map.removeBy2("A");
System.out.println("map = " + map);
System.out.println("map.mapToV = " + map.mapToV);
System.out.println("map.map1to2 = " + map.map1to2);
System.out.println("map.map2to1 = " + map.map2to1);
}
}
Does anyone knwo a better solution? Bonus points if it were to work for a variable number of keys and use a smart locking scheme.
NOTE: The solution is required to allow access by either key separately. So a traditional CompositeKey does not work, since the hash code cannot be calculated with only either key.
Thanks in advance
专注分享java语言的经验与见解,让所有开发者获益!
评论