问题描述:
发信人: cellulose (▄︻┻┳═一), 信区: CPlusPlus
标 题: 请问如何实现这种Multi-Key Multi-Map
发信站: 水木社区 (Tue May 29 14:13:44 2007), 站内
名字可能不是太准确,但差不多就是这个意思
Multi-Key Multi-Map
即一个multimap支持multikey
先考虑两个key的情况
基本上可以这么实现
multimap<pair<pKey, sKey>, Data>
key部分按照pair默认的 < 排序,即先排pKey,再排sKey
现在有个要求就是可以选择一行,即找出所有pKey 为某值的 iterator,
显然这组值是连续的,可以用一个范围来表示
问题是要求知道 sKey对应类型的最大值和最小值,才能很方便的选择一行
例如假设multimap是这种情况
typedef multimap<pair<string,unsigned char>, string> MKMap;
typedef MKMap::Iterator MKIterator;
那么选择某sKey可以这么实现
MKMap mkMap;
//填入数据
//。。。
//
pair<MKIterator, MKIterator> SelectRow(string pkey)
{
return make_pair(mkMap.lower_bound(make_pair(pkey,0)),
mkMap.upper_bound(make_pair(pkey,0xff)));
}
这里的0和0xff就是sKey对应类型的最小值和最大值
如果考虑使用与任何类型,应该怎么实现?
其实我本来是考虑做一个多string为key的一个multimap
那么string里面最小的就是空串了,最大的是什么呢?
分析解决:
找找 boost 的 Multi-index Containers
value 和 key 可以相互映射的叫 bidirectional map,不是 mulit-key map.
楼主这里的 multikey 用 muliti-index 说更合适,指的是 key 有多维,可以按每一维来做查询,应该不是指 bidirectional map。
我以前一个项目就是类似的,
每个value对应2个key,目标是无论知道哪个key都可以返回这个value
和你说的多维key,知道其中一维,的区别应该就是2个和多个。
我的做法是直接写一个类继承自apache的MultiKeyMap
import java.util.*;
import org.apache.commons.collections.keyvalue.MultiKey;
import org.apache.commons.collections.map.*;
/**
* 多个key的映射
* @author Administrator
*
*/
public class MultiMap extends MultiKeyMap {
private static final long serialVersionUID = -3218199231038721040L;//changed a little bit
public MultiMap(){
super();
}
public synchronized Object put(Object key1,Object key2,Object value){
return super.put(key1,key2,value);
}
/**
* 是否包含key
*
* @param key
* @return
*/
public boolean contains(Object key){
if(map.containsKey(key)){
return true;
}
if(map.keySet().contains(key)){
return true;
}
Iterator it = map.keySet().iterator();
while(it.hasNext()){
Object tmp = it.next();
if(tmp instanceof MultiKey){
Object[] keys = ((MultiKey)tmp).getKeys();
for(int i=keys.length-1;i>=0;i--){
if(key.equals(keys[i])){
return true;
}
}
}
}
return false;
}
/**
* 根据key,取出对应的value
*/
public Object get(Object key){
Iterator it = map.keySet().iterator();
while(it.hasNext()){
Object tmp = it.next();
MultiKey obj = null;
if(tmp instanceof MultiKey){
obj = (MultiKey)tmp;
Object[] keys = obj.getKeys();
boolean has = false;
for(int i=keys.length-1;i>=0;i--){
if(key.equals(keys[i])){
has = true;
break;
}
}
if(has){
return super.get(obj);
}
}
}
return null;
}
}