Java 具有不同可能值类型的HashMap
想象一下这样的情况:Java 具有不同可能值类型的HashMap,java,Java,想象一下这样的情况: class AbstractClass{void sharedMethod()} class ClassOne extends AbstractClass{void sharedMethod(); void specificMethod()} class ClassTwo extends AbstractClass{void sharedMethod(); void specificMethod2()} 我想在地图中存储以下内容: HashMap<String, L
class AbstractClass{void sharedMethod()}
class ClassOne extends AbstractClass{void sharedMethod(); void specificMethod()}
class ClassTwo extends AbstractClass{void sharedMethod(); void specificMethod2()}
我想在地图中存储以下内容:
HashMap<String, List<SOMETHING_I_DON'T_KNOW_IN_ADVANCE>> hm = new HashMap<>();
hm.put("blabla", List<ClassOne>);
hm.put("blublu", List<ClassTwo>);
HashMap在AbstractClass中创建“Abstractvoid specificMethod()”,然后在具体类中创建specificMethod()的具体版本是否适合您
这样,您就不必担心是调用specificMethodOne()还是调用specificMethodTwo()。。。AbstractClass对象已经知道应该使用哪个版本的specificMethod()
我知道我可以将AbstractClass作为映射的值类型,但我希望能够访问我的特定方法
我假设您希望这样做:
List<ClassOne> one = hm.get("blabla");
one.specificMethod();
// or
List<ClassTwo> two = hm.get("blublu");
two.specificMethod2();
是的,这是粗略的和容易出错的,但是使用java泛型没有简单的方法。
我会考虑将数据封装在一个类中,例如
private static class MyMessages
{
final List<ClassOne> typeOneMessages = new ArrayList<>();
final List<ClassTwo> typeTwoMessages = new ArrayList<>();
public void addTypeOne(ClassOne c) {
typeOneMessages.add(e);
}
// add appropriate getter methods; or a stream
public Stream<ClassOne> streamOne()
{
return typeOneMessages.stream();
}
// same for type two
}
私有静态类MyMessages
{
最终列表typeOneMessages=new ArrayList();
最终列表typeTwoMessages=new ArrayList();
公共无效addTypeOne(一级c){
添加(e);
}
//添加适当的getter方法;或流
公共流streamOne()
{
返回typeOneMessages.stream();
}
//第二类也一样
}
或者按照Rick Stabile的建议,在抽象类中定义一个方法
如果您希望将它们放在一起,则必须考虑检索,例如:
public static void main(String[] args)
{
final Map<String, List<? extends AbstractClass>> map = new HashMap<>();
List<ClassOne> ones = new ArrayList<>();
for (int i = 0; i < 4; i++) {
ones.add(new ClassOne());
}
List<ClassTwo> twos = new ArrayList<>();
for (int i = 0; i < 8; i++) {
twos.add(new ClassTwo());
}
map.put("ones", ones);
map.put("twos", twos);
List<? extends AbstractClass> out = map.get("ones");
// can call shared method on the contents
out.stream().forEach(a -> a.sharedMethod());
// will have to cast to the specific type
out.stream().filter(a -> a instanceof ClassOne)
.forEach(c1 -> ((ClassOne)c1).specificMethod());
List<? extends AbstractClass> out2 = map.get("twos");
// can call shared method on the contents
out2.stream().forEach(a -> a.sharedMethod());
// will have to cast to the specific type 2
out2.stream().filter(a -> a instanceof ClassTwo)
.forEach(c2 -> ((ClassTwo)c2).specificMethod2());
}
publicstaticvoidmain(字符串[]args)
{
最终映射您可以通过使用“通配符(?)参数”实现这一点,并且由于“类型安全”机制,强制转换是不可避免的。
这对我很有用:
HashMap<String, List<? extends AbstractClass>> hm = new HashMap<>();
ClassOne class1 = new ClassOne();
ClassTwo class2 = new ClassTwo();
List<ClassOne> c1l = new ArrayList<>();
c1l.add(class1);
List<ClassTwo> c2l = new ArrayList<>();
c2l.add(class2);
hm.put("blabla", c1l);
hm.put("blublu", c2l);
@SuppressWarnings("unchecked")
List<ClassOne> xyy = (List<ClassOne>)hm.get("blabla");
ClassOne c1 = xyy.get(0);
c1.specificMethod1();
所以,当您检索某个对象时,您如何知道是否可以调用specificMethod()
或specificMethod2()
?例如,如果我这样做:hm.get(“blablabla”).get(0)->我将知道我正在获取一个ClassOne对象,因此我将知道我有权访问specificMethod(),对不起,为什么您知道“blablabla”是ClassOne吗?为什么一个字符串键能保证一个给定的对象?因为这是我决定要做的映射。实际上,键部分对应于一种消息类型,值部分对应于这种类型的所有消息的列表。例如:hm.put(1,list)那没有意义。如果有人给你一个任意的字符串,而你不知道它是什么呢?那么你会分配给什么类型的列表
?你为什么不直接编写类Foo{List blablabla;List blublu;}
HashMap<String, List<? extends AbstractClass>> hm = new HashMap<>();
ClassOne class1 = new ClassOne();
ClassTwo class2 = new ClassTwo();
List<ClassOne> c1l = new ArrayList<>();
c1l.add(class1);
List<ClassTwo> c2l = new ArrayList<>();
c2l.add(class2);
hm.put("blabla", c1l);
hm.put("blublu", c2l);
@SuppressWarnings("unchecked")
List<ClassOne> xyy = (List<ClassOne>)hm.get("blabla");
ClassOne c1 = xyy.get(0);
c1.specificMethod1();
Hello! from SpecificMethod1