我想创建一种内存数据库,我可以在其中放置任何类型的对象EntityProxy
。我想根据每个对象的类型和ID号(每个EntityProxy
都有 - 为每个对象编制索引 - 就像为每种类型创建一个HashMap一样简单。
我可以用
之类的东西手动实现public void put(Object o)
{
if (o instanceof Car)
carIndex.put(o.getId(), o);
else if (o instanceof Bus)
busIndex.put(o.getId(), o);
...
}
但我当然不想。我想要更像
的东西public void <T extends EntityProxy> put(T o)
{
indexMap.get(o.class).put(o.getId(), o);
}
我只是不放弃使用泛型词汇来做到这一点。我不知道问号在模板定义中意味着什么,真的 - 会像
HashMap<Class<?>, HashMap<Long, EntityProxy>> indexMap
工作?
答案 0 :(得分:2)
那张地图还可以;如果你真的需要添加一点约束,那就试试吧:
Map<Class<? extends EntityProxy>, HashMap<Long, EntityProxy>> indexMap;
这将确保密钥类只能是EntityProxy.class或子类。
您可以将问号视为某些“任何东西”,但匿名。所以<?>
表示真的是 - 任何Object
,<? extends EntityProxy>
表示满足此条件的任何内容(通过“instanceof EntityProxy
”测试)。< / p>
此处的类型安全性低于预期,因为您仍然可以将任何内容作为键和任何内容放在该映射中。我的意思是,你可以合法地把它放在地图上:
indexMap.put(EntityProxy1.class, new HashMap<Long, EntityProxy2>());
(假设EntityProxy1
和EntityProxy2
都是EntityProxy
的子类),因为密钥和值之间没有相关性。要强制执行此操作,需要按照以下方式声明映射的put()
方法:
<T extends EntityProxy> put(Class<T> key, HashMap<Long, T> value);
T
与?
非常相似,但主要区别在于它为您提供了一个可以在该上下文中引用它的名称。
所以,如果我说?
代表“任何东西”,我会说T
代表“某事”,因为一旦你宣布它就可以引用那些东西。
但是你需要一个自定义数据结构,因为java.util.Map
不提供这种约束。如果您正在使用它,如代码示例中所示,我认为您确实不需要这些强制执行。
答案 1 :(得分:1)
请注意,在此示例中,我使用了List。您可以轻松地将此替换为您的Collection
选择类并进行相应调整。
public interface Classifiable {
String classification();
}
public abstract class Automobile implements Classifiable {
// String classification defined in child classes
}
public class Car extends Automobile {
public String classification() { return "Car"; }
}
public class Bus extends Automobile {
public String classification() { return "Bus"; }
}
public class AutoMap {
Map<String,List<Automobile>> theMap = new Map<String,List<Automobile>>();
public AutoMap() { }
public void add(Automobile a) {
String type = a.classification();
List<Automobile> list = theMap.get(type);
if(list == null) {
list = new LinkedList<Automobile>();
theMap.put(type,list);
}
list.add(a);
}
public List<Automobile> getAutosOfType(String type){
return theMap.get(type);
}
}
public static void main(String[] args) {
List<Automobile> autos = getRandomAutos(); // defined somewhere? :)
AutoMap theAutomap = new AutoMap();
}
答案 2 :(得分:1)
如果你不介意使用类名,那就简单如下:
public void <T extends EntityProxy> put(T o)
{
HashMap map = indexMap.get(o.getClass().getName());
if (map == null)
{
map = new HashMap();
indexMap.put(o.getClass().getName(), map);
}
map.put(o.getId(), o);
}
此代码将在您继续创建所需的子哈希图。
如果您使用getClass().getName()
,则会在com.mypackage.Bus
表单上获取姓名。如果您愿意处理名称冲突并且只想要简单名称(在本例中为“Bus”),请改用getClass().getSimpleName()
。
答案 3 :(得分:1)
尝试:
Map<Class<?>, Map<Long, EntityProxy>> indexMap = new HashMap<Class<?>, Map<Long, EntityProxy>>();
和
public void put(EntityProxy entityProxy){ // generics don't add anything here
...
(我没有测试过)