Chinaunix首页 | 论坛 | 博客
  • 博客访问: 83610
  • 博文数量: 5
  • 博客积分: 140
  • 博客等级: 民兵
  • 技术积分: 60
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-01 10:08
文章分类
文章存档

2015年(1)

2013年(1)

2012年(3)

我的朋友

分类: Java

2013-02-16 17:05:25

很多场景下,对于某些元数据,经常会出现按多种条件查询的情况

举个简单的例子

public class ServiceMeta {
    private int serviceId;
    private int serviceType;
    private int serviceLevel;
    private int parentId;
    private int status;

    /**getters and setters**/
}

这个元数据类中,在实际应用中可能会根据ID/TYPE/LEVEL/STATUS单独或组合条件进行查询。

元数据的特点一般是:固定,数据量不是非常大,数据使用密度高。

在计算密度非常大的应用中,利用数据库的sql语句来做查询显然是不明智的,更多地是将元数据加载到内存中,通过集合存储,在使用的时候遍历查询获取数据。

public class MetaManager {
    priavet Set metaSet;

    public ServiceMeta getServiceById (int id) {
        for (ServiceMeta meta : metaSet) {
            if (meta.getServiceId() == id)
                return meta;
        }
        return null;
    }

    /**other get methods**/
}

当然,这种方式的一个明显的缺点在于,过多的循环会严重影响系统的性能。因此,明智的选择是根据最常用的KEY建立映射关系,这样能有效地增加查询效率

public class MetaManager{
    praivet Map metaMap;

    pulic ServiceMeta getServiceMetaById (int id) {
        return metaMap.get(new Integer(id));
    }

    public ServiceMeta getServiceMetaByType(int type){
        for (ServiceMeta meta : metaMap.values()){
            if(meta.getType()==type)
                return meta;
        }
        return null;
    }

    /**other get methods**/
}

好吧,在绝大部分查询都是使用单一类型的索引的情况下,上述代码可以很好得完成工作。

但是问题在于,当存在多个索引的时候呢?

在没有很好的解决方案的时候,通常会考虑使用两个map来实现,如上例中,同时建立

private Map idMap;
private Map typeMap;

也可以避免频繁地查询,但是随之而来的问题,开发者需要同时维护多个map,当索引多到一定程度时,所有map的维护就会需要相当大的代价

因此一种更好的做法就是建立一个这样的关联关系

private Map>

通过对KEY类型建立映射关系来解决问题。

这似乎看起来很美好,代码可以节省很多,但是由于某些细节,使用者还是需要关心KeyMeta与Key(例子中的Integer)的关系

如果调用者不想关心KeyMeta与Key的关心,那就只能将这个关系交给操作这个复合Map的相关类了,于是就会对这个Map封装在某个类中,使之成为单独的一个工具。

本文作者由于喜欢偷懒,因此这里使用guava的table来代替Map>

其实HashBasedTable底层也是HashMap>的实现,当然google做了更多优化就是了

于是就有了以下的工具类:

/**
 * 多维度KEY对同一个value的映射关系表
 *
 * @author KOsteve
 * @version 1.0.0, 6/2/13
 * @since 1.0.0
 *
 */
public class WiMap {
/**
* 维度信息
*/
private final Set> metaSet;


/**
* 数据存储
*/
private Table, K, V> table;


public WiMap(Set> metaSet) {
super();
this.metaSet = metaSet;
table = HashBasedTable.create();
}


public V get (K key) {
WiKeyMeta meta = this.getMetaByKey(key);
if (meta != null) {
return table.get(meta, key);
}
return null;
}


public V put (K key, V value) {
WiKeyMeta meta = this.getMetaByKey(key);
if (meta != null) {
return table.put(meta, key, value);
}
return null;
}


public int size() {
return table.size();
}


public boolean isEmpty() {
return table.isEmpty();
}


public boolean containsKey(K key) {
WiKeyMeta meta = this.getMetaByKey(key);
if (meta != null) {
return table.containsColumn(key);
}
return false;
}


public boolean containsValue(Object value) {
return table.containsValue(value);
}


public V remove(K key) {
WiKeyMeta meta = this.getMetaByKey(key);
if (meta != null) {
return table.remove(meta, key);
}
return null;
}


public void clear() {
table.clear();
}


public Set keySet() {
return table.columnKeySet();
}


public Collection values() {
return table.values();
}


public Set> getMetaSet() {
return metaSet;
}


private WiKeyMeta getMetaByKey (K key) {
for (WiKeyMeta meta : metaSet) {
if (meta.getKeyClazz().isInstance(key)) {
return meta;
}
}
return null;
}
}
/**
 * WiMap维度信息定义
 * @author KOsteve
 * @version 1.0.0, 6/2/13
 * @since 1.0.0
 *
 */
public class WiKeyMeta {
/**
* 维度名称
*/
private final String meta;


/**
* 键值类
*/
private final Class keyClazz;


public WiKeyMeta(String meta, Class keyClazz) {
this.meta = meta;
this.keyClazz = keyClazz;
}


public String getMeta() {
return meta;
}


public Class getKeyClazz() {
return keyClazz;
}


@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}


@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}


}
阅读(2245) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~