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