Java 以类为键的树映射

Java 以类为键的树映射,java,class,generics,interface,treemap,Java,Class,Generics,Interface,Treemap,我试图为不同类的对象编写一种注册表 我有以下资料: public interface DbObject{ void setId(long id); Long getId(); } public class BasicDbObject implements DbObject{ private long id=null; void setId(long id){ this.id=id; } Long getId(){

我试图为不同类的对象编写一种注册表

我有以下资料:

public interface DbObject{
    void setId(long id);
    Long getId();
}
public class BasicDbObject implements DbObject{
    private long id=null;
    void setId(long id){
        this.id=id;
    }
    Long getId(){
        return id;
    }
}
BasicObject bo = registry.get(BasicObject.class).get(42);
实现此接口的原型类如下所示:

public interface DbObject{
    void setId(long id);
    Long getId();
}
public class BasicDbObject implements DbObject{
    private long id=null;
    void setId(long id){
        this.id=id;
    }
    Long getId(){
        return id;
    }
}
BasicObject bo = registry.get(BasicObject.class).get(42);
我想构建这个接口的各种不同实现。 我希望能够有一个映射对象,它从每个实现类映射到一个实例映射

大概是这样的:

Map <Class<C implements DbObject> , Map<Long, C>> registry = new TreeMap/HashMap/SomeOtherKindOfMap (...)
假想我做了什么

BasicObject bo=new BasicObject(...);
innerMap = new SomeMap<Long,BasicObject>();
innerMap.put(42,bo);
registry.put(BasicObject.class,innerMap);
BasicObject bo=新的BasicObject(…);
innerMap=newsomeMap();
innerMap.put(42,bo);
put(BasicObject.class,innerMap);
以前

请告诉我,如果这还不清楚,我很难解释,因为英语不是我的母语

先谢谢你


编辑:

事实证明,当围绕地图定义泛型类时,我可以做一些非常接近我想要做的事情:

public class ObjectRegistry <T extends DbObject>{

    private HashMap<Class<T>, TreeMap<Long,T>> registry=null;

    ObjectRegistry(){
        registry=new HashMap<Class<T>, TreeMap<Long,T>>();
    }
    public void register(T dbObject){
        TreeMap<Long, T> map = registry.get(dbObject.getClass());
        if (map==null){
            map=new TreeMap<Long,T>();
            registry.put((Class<T>) dbObject.getClass(),map);
        }
        map.put(dbObject.getId(),dbObject);
    }

    public <T extends DbObject>T get(Class<T> objectClass,long id){
        TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(objectClass);
        if (map != null){
            return map.get(id);
        }
        return null;
    }

    public TreeMap<Long,T> getAll(Class<T> dbObjectClass) {
        return registry.get(dbObjectClass);
    }
}
公共类ObjectRegistry{
私有HashMap注册表=null;
ObjectRegistry(){
registry=newhashmap();
}
公共无效寄存器(DBT对象){
TreeMap map=registry.get(dbObject.getClass());
if(map==null){
map=newtreemap();
registry.put((Class)dbObject.getClass(),map);
}
put(dbObject.getId(),dbObject);
}
公共T get(类objectClass,长id){
TreeMap map=(TreeMap)registry.get(objectClass);
if(map!=null){
返回map.get(id);
}
返回null;
}
公共树映射getAll(类dbObjectClass){
返回registry.get(dbObjectClass);
}
}
我对内部映射使用树形图,因为我想方便地返回按id排序的类实例

因此,问题是: 有没有一种方法可以做到这一点,而不必在类标题中使用
子句


编辑2:

再想一想,约翰的答案恰恰是这个问题的答案

这是我的最终代码:

HashMap<Class<? extends DbObject>, TreeMap<Long, ? extends DbObject>> registry = null;

public <T extends DbObject> T get(Class<T> clazz, long id) {
    TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(clazz);
    if (map != null) {
        return map.get(id);
    }
    return null;
}

public <T extends DbObject> void register(T dbObject) {
    TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(dbObject.getClass());
    if (map == null) {
        map = new TreeMap<Long, T>();
        registry.put((Class<T>) dbObject.getClass(), map);
    }
    map.put(dbObject.getId(), dbObject);
}


public <T extends DbObject> TreeMap<Long, T> getAll(Class<T> dbObjectClass) {
    return (TreeMap<Long, T>) registry.get(dbObjectClass);
}
HashMap
所以我想知道的是:有没有可能在树映射中将类对象作为键

TreeMap
取决于键空间上是否存在总的顺序,由具有自然顺序的键类型(通过实现
compariable
)或您提供的单独的
比较器
对象建立<代码>类
es没有自然顺序。可以想象,您可以编写一个合适的
比较器
,但在我看来,这似乎是非常做作的

但是为什么您特别需要一个
树形图
?您没有描述任何需求,这些需求至少可以通过任何其他类型的
Map
得到很好的解决。特别是,我几乎总是发现
HashMap
是一个更好的选择,我看不出有任何理由认为它不适合这一个。它当然可以将
Class
类型的对象作为键

此外,如果确实不需要任何特定的实现,那么最好将类型简单地声明为
Map
。这样,您实际上可以提供任何
Map
实现,甚至可以在发现原因时更改您提供的实现

声明从实现类C映射到映射对象的映射对象的语法是什么?每个映射对象从一个长对象(id)映射到C的实例

您要求每个值的类型上的约束依赖于关联键的类型,但无法声明强制这种关系的类型。特定键或特定值是否适用于
映射
仅是映射类型的函数,而不是其他类型的函数

您可以围绕地图的访问编写通用方法,以提供所需的外观,但数据检索方法需要强制转换。例如:

Map<Class<? extends DbObject>, Map<Long, ? extends DbObject>> registry = /*...*/;

<T extends DbObject> Map<Long, T> getRegistryMap(Class<T> clazz) {
    return (Map<Long, T>) registry.get(clazz);
}

<T extends DbObject> T get(Class<T> clazz, Long id) {
    Map<Long, T> map = getRegistryMap(clazz);

    return (map == null) ? null : map.get(id);
}

<T extends DbObject> T put(Class<T> clazz, Long id, T obj) {
    Map<Long, T> map = getRegistryMap(clazz);

    if (map == null) {
        map = new HashMap<>();
        registry.put(clazz, map);
    }
    return map.put(id, obj);
}

MapIt不是关于树形图的,我知道我可以使用其他类型的地图。这是关于声明地图的语法。@StephanRichter,更新答案以解决您澄清的问题。好的,这基本上就是我想知道的。我会让它开放几天,也许有人有更好的想法/解决方法/什么的。如果没有,我会在接下来的几天里把你的答案标记为正确。谢谢,到目前为止。请再次编辑问题。我非常接近于一个解决方案。够了,这几乎和你建议的解决方案一样,现在我又读了一遍。@StephanRichter,为什么这么奇怪?无论如何,我已经更新了我的答案,以解决您的问题更新。我真的希望这件事现在已经解决了。