gpt4 book ai didi

java - 以类为键的 TreeMap

转载 作者:行者123 更新时间:2023-11-30 08:08:50 25 4
gpt4 key购买 nike

我正在尝试为不同类的对象编写一种注册表。

我有以下内容:

public interface DbObject{
void setId(long id);
Long getId();
}

实现此接口(interface)的原型(prototype)类如下:

public class BasicDbObject implements DbObject{
private long id=null;
void setId(long id){
this.id=id;
}
Long getId(){
return id;
}
}

我想构建此接口(interface)的各种不同实现。我希望能够拥有一个 Map 对象,它从每个实现类映射到实例的 Map。

像这样:

Map <Class<C implements DbObject> , Map<Long, C>> registry = new TreeMap/HashMap/SomeOtherKindOfMap (...)

我知道我可以做类似的事情

Map <String,Map<Long,DbObjects>> registry = new ...

但这样一来,我将不得不编写更多代码来确定名称、比较类等。有没有更简单的方法来完成此操作?

所以我想知道的是:是否可以将类对象作为 TreeMap 中的键?

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

我希望能够执行如下请求:

BasicObject bo = registry.get(BasicObject.class).get(42);

确保 id 做了

BasicObject bo=new BasicObject(...);
innerMap = new SomeMap<Long,BasicObject>();
innerMap.put(42,bo);
registry.put(BasicObject.class,innerMap);

之前。

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

提前谢谢你。


编辑:

事实证明,在围绕 map 定义通用类时,我可以做一些非常接近我想要的事情:

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);
}
}

我使用 TreeMap 进行内部映射,因为我想轻松返回按 id 排序的 Class 实例。

所以提炼后的问题是:有没有办法做到这一点,没有 <T extends DbObject>类头中的子句?


编辑 2:

再想一想,原来John的回答正是解决这个问题的方法。

这是我的最终代码:

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);
}

它不需要 <T extends DbObject>类头中的子句。

最佳答案

So what I want to know: is it possible to have class objects as keys in a tree map?

TreeMap取决于 key 空间的总顺序,由具有自然顺序的 key 类型(通过实现 Comparable )或单独的 Comparator 确定您提供的对象。 Class es 没有自然顺序。可以想象你可以写一个合适的 Comparator ,但这对我来说似乎很做作。

但是为什么你特别需要一个 TreeMap ?您没有描述任何其他类型的 Map 至少不能很好地解决的要求.特别是,我几乎总能找到 HashMap是一个更好的选择,我看不出有任何理由不适合这个选择。它当然可以有 Class 类型的对象作为键。

此外,如果您确实不需要任何特定的实现,那么您最好声明类型简单地为Map。 .这样你实际上可以提供任何Map实现,如​​果您发现有理由这样做,甚至可以更改您提供的实现。

What would be the syntax to declare a map object, that maps from implementing classes C to a map objects each mapping from a long object (the id) to instances of C?

您要求对每个值的类型的约束取决于关联键的类型,但是没有办法声明强制这种关系的类型。特定键或特定值是否适合 Map是 map 类型单独的函数,而不是彼此类型的函数。

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

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);
}

更新添加:

So the refined question is: Is there a way to do this, without the <T extends DbObject> clause in the Class head?

是的,我已经写过了。只需在它周围打一个简单的类声明即可。您不需要泛型类就可以拥有泛型方法。事实上,两者是正交的。泛型类的常规方法可以使用该类的类型参数。这不会使它们成为通用方法。如果一个方法声明它自己的类型参数,那么它就是泛型的,就像我上面做的那样。你的get()方法也这样做,重要的是要理解类型参数 <T>您在方法签名中显式声明隐藏了类的同名类型参数:它是一个不同的 T .

关于java - 以类为键的 TreeMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32893389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com