user617136
user617136

Reputation: 323

Java Map where the Value is a List of values of the same type as the key

What I would like to have is something like this:

public abstract Class Content {
    private Map<Class<? extends Content>, List<? extends Content>> relations;
}

Content has a bunch of subclasses - A,B,C,D etc...

The most frequent use case is to get all A's:

public List<A> getA() {
    return (List<A>)relations.get(A.class);
}

Kind of ok - apart from the ugly cast.

But the real problem is there's nothing stopping me from doing something stupid like:

relations.put(A.class, List<B> myListOfBs);

So a call to getA() above would result in a horrible cast exception. Is there any way I can write it so the compiler would warn me in the above example - and also remove the need for the ugly cast.

Thanks

Upvotes: 3

Views: 193

Answers (2)

Bohemian
Bohemian

Reputation: 424983

Create a custom Map interface that fixes the type to the same type:

interface RelatedMap<T> extends Map<Class<T>, List<T>> {}

then

private RelatedMap<? extends Content> relations;

Upvotes: 0

Mark Peters
Mark Peters

Reputation: 81074

You can create a wrapper around a Map and use a generic method to constrain your put method:

 public class HeterogeneousContainer {
     private final Map<Class<? extends Content>, List<? extends Content>> map;

     public <T extends Content> void put(Class<T> type, List<T> values) {
         map.put(type, values);
     }


     public <T extends Content> List<T> get(Class<T> type) {
         //this warning can be safely suppressed after inspection
         return (List<T>) map.get(type); 
     }
 }

Now you know that as long as the users of the container aren't using it improperly (i.e. in raw form) then the key and value must correspond...you couldn't call put(B.class, listOfAs);.

Upvotes: 3

Related Questions