views:

1014

answers:

2

hi all,

if i have two hashmaps, of types

HashMap<Integer, HashMap<Integer, Police>> time_id_police;  
HashMap<Integer, HashMap<Integer, Ambulance>> time_id_ambulance;

where Police and Ambulance both extend Rescue, how can i have a method like

HashMap<Integer, HashMap<Integer, Rescue>> getRescue(){
   if (a) return time_id_police;
   else return time_id_ambulance;
}

neither this, nor changing the return type to

HashMap<Integer, HashMap<Integer, ? extends Rescue>>

seems to work.

thanks a lot.

A: 

Change your declarations of time_id_police and time_id_ambulance to

HashMap<Integer, HashMap<Integer, Rescue>> time_id_police;
HashMap<Integer, HashMap<Integer, Rescue>> time_id_ambulance;

you might also want to declare them as Map instead of HashMap, this way if you ever decide to change the Map implementation you use, you'll only have to make a change in one place (where you instanciate your object) rather than in many places (where you use your object)

Map<Integer, Map<Integer, Rescue>> time_id_police = new HashMap<Integer, HashMap<Integer, Rescue>>();
Glen
With these changes how can you be sure that no Ambulance is put into time_id_police ?
Zed
Those types of `time_id_*` are wrong...
Tom Hawtin - tackline
@Zed, you can't. The best workaround might be to create a wrapper class that hides the implementation details from the users of the police and ambulance collections
Glen
@Tom, how so? I don't see a problem, but I am having a slow day, so that means nothing
Glen
Well you would still want to be able to do `time_id_police.get(x).get(y)` and still end up with `Police` and not just `Rescue`.
Tom Hawtin - tackline
@Tom, yup, having a slow day. I see what you mean.
Glen
A: 

Clearly HashMap<Integer, HashMap<Integer, Rescue>> is wrong because then a value could be replaced in time_id_police with a HashMap<Integer, Ambulance>. A similar thing could be done if you replaced Rescue with ? extends Rescue.

However, using ? extends twice gives us something that wont break the type system.

HashMap<Integer, ? extends HashMap<Integer, ? extends Rescue>> getRescue() {

Most Java programmers prefer to use the more general Map in types rather than a specific implementation.

Map<Integer, ? extends Map<Integer, ? extends Rescue>> getRescue() {

Incidentally, if you change the body of your method to use the more concise ternary operator:

   return a ? time_id_police : time_id_ambulance;

You get a slightly more helpful error message, as the compiler works out the type for you:

R.java:18: incompatible types
found   : java.util.HashMap<java.lang.Integer,capture of ? extends java.util.HashMap<java.lang.Integer,? extends Rescue>>
required: java.util.HashMap<java.lang.Integer,java.util.HashMap<java.lang.Integer,Rescue>>
   return a ? time_id_police : time_id_ambulance;
        ^
1 error
Tom Hawtin - tackline
just what i wanted. rather verbose though, because the real map is 5 levels deep :) thanks a lot
I don't exactly know what you are doing, but perhaps it might be worth introducing a key object - a single object composing the fives keys you would use for your nested maps.
Tom Hawtin - tackline