views:

4459

answers:

8

What is the difference between the following maps I create (in another question, people answered using them seemingly interchangeably and I'm wondering if/how they are different):

HashMap<String, Object> map = new HashMap<String, Object>();
Map<String, Object> map = new HashMap<String, Object>();
+1  A: 

You create the same maps.

But you can fill the difference when you will use it. With first case you'll be able to use special HashMap methods (but I don't remember anyone realy useful), and you'll be able to pass it as a HashMap parameter:

public void foo (HashMap<String, Object) { ... }

...

HashMap<String, Object> m1 = ...;
Map<String, Object> m2 = ...;

foo (m1);
foo ((HashMap<String, Object>)m2);
Roman
+15  A: 

There is no difference between the objects. There is a difference in the interface you have to the object. In the first case, the interface is HashMap<String, Object>, whereas in the second it's Map<String, Object>. The underlying object, though, is the same.

The advantage to using Map<String, Object> is that you can change the underlying object to be a different kind of map without breaking your contract with any code that's using it. If you declare it as HashMap<String, Object>, you have to change your contract if you want to change the underlying implementation.

T.J. Crowder
so the only difference is when i pass it as a parameter for example then i need to reference one as Map<blah> and the other as HashMap<blah> but they are indeed the same exact type of object?
hatorade
Yes, they're the exact same object, it's about the *contract* you're forming with any code using it. I updated the answer a bit to clarify.
T.J. Crowder
ah, so the difference is that in general, Map has certain methods associated with it. but there are different ways or creating a map, such as a HashMap, and these different ways provide unique methods that not all maps have. So if I use a Map, I can only use Map methods, but I have a HashMap underneath so any speed benefits, search benefits, etc of HashMap will be seen in the Map. And if I used a HashMap, I could use those HashMap specific methods and if I ultimately need to change the map type it's a lot more work.
hatorade
Pretty much. Remember that the implementation (speed, etc.) is the same either way. Read up on interfaces for more info, it's useful to know.
T.J. Crowder
not necessarily though, right? if i say map, but i have a hashmap underneath, and i use some method specific to map, it might go faster with hashmap than if the map was a different type of map, right? i'm think like how you can implement a queue in many different ways but some do the same methods faster than others even though they all share the method (like sort, etc).
hatorade
I think what he's saying is that even if you're referring to a HashMap as a Map, the implementation remains HashMap and so nothing changes about how the methods execute. If you changed the implementation behind the Map interface, properties of execution (such as speed) could indeed change.
ColinD
+2  A: 

In your second example the "map" reference is of type Map, which is an interface implemented by HashMap (and other types of Map). This interface is a contract saying that the object maps keys to values and supports various operations (e.g. put, get). It says nothing about the implementation of the Map (in this case a HashMap).

The second approach is generally preferred as you typically wouldn't want to expose the specific map implementation to methods using the Map or via an API definition.

Adamski
A: 

Map is the Interface and Hashmap is the class that implements that.

So in this implementation you create the same objects

Diego Dias
+3  A: 

As noted by TJ Crowder and Adamski, one reference is to an interface, the other to a specific implementation of the interface. According to Joshua Block, you should always attempt to code to interfaces, to allow you to better handle changes to underlying implementation - i.e. if HashMap suddenly was not ideal for your solution and you needed to change the map implementation, you could still use the Map interface, and change the instantiation type.

aperkins
+4  A: 

Map is an interface that HashMap implements. The difference is that in the second implementation your reference to the HashMap will only allow the use of functions defined in the Map interface, while the first will allow the use of any public functions in HashMap (which includes the Map interface).

It will probably make more sense if you read Sun's interface tutorial

Graphics Noob
+1  A: 

Map is the static type of map, while HashMap is the dynamic type of map. This means that the compiler will treat your map object as being one of type Map, even though at runtime, it may point to any subtype of it.

This practice of programming against interfaces instead of implementations has the added benefit of remaining flexible: You can for instance replace the dynamic type of map at runtime, as long as it is a subtype of Map (e.g. LinkedHashMap), and change the map's behavior on the fly.

A good rule of thumb is to remain as abstract as possible on the API level: If for instance a method you are programming must work on maps, then it's sufficient to declare a parameter as Map instead of the stricter (because less abstract) HashMap type. That way, the consumer of your API can be flexible about what kind of Map implementation they want to pass to your method.

Matthias
A: 

I was just going to do this as a comment on the accepted answer but it got too funky (I hate not having line breaks)

ah, so the difference is that in general, Map has certain methods associated with it. but there are different ways or creating a map, such as a HashMap, and these different ways provide unique methods that not all maps have.

Exactly--and you always want to use the most general interface you possibly can. Consider ArrayList vs LinkedList. Huge difference in how you use them, but if you use "List" you can switch between them readily.

In fact, you can replace the right-hand side of the initializer with a more dynamic statement. how about something like this:

List collection;
if(keepSorted)
    collection=new LinkedList();
else
    collection=new ArrayList();

This way if you are going to fill in the collection with an insertion sort, you would use a linked list (an insertion sort into an array list is criminal.) But if you don't need to keep it sorted and are just appending, you use an ArrayList (More efficient for other operations).

This is a pretty big stretch here because collections aren't the best example, but in OO design one of the most important concepts is using the interface facade to access different objects with the exact same code.

Edit responding to comment:

As for your map comment below, Yes using the "Map" interface restricts you to only those methods unless you cast the collection back from Map to HashMap (which COMPLETELY defeats the purpose).

Often what you will do is create an object and fill it in using it's specific type (HashMap), in some kind of "create" or "initialize" method, but that method will return a "Map" that doesn't need to be manipulated as a HashMap any more.

If you ever have to cast by the way, you are probably using the wrong interface or your code isn't structured well enough. Note that it is acceptable to have one section of your code treat it as a "HashMap" while the other treats it as a "Map", but this should flow "down". so that you are never casting.

Also notice the semi-neat aspect of roles indicated by interfaces. A LinkedList makes a good stack or queue, an ArrayList makes a good stack but a horrific queue (again, a remove would cause a shift of the entire list) so LinkedList implements the Queue interface, ArrayList does not.

Bill K
but in this example, i only get the methods from the general List class, right? regardless of whether I make it a LinkedList() or an ArrayList()? it's just that if I use insertion sort (which I imagine must be a method for List that LinkedList and ArrayList get by inheritance) it works way faster on the LinkedList?
hatorade
i guess what i'm looking for is whether or not when I say Map<string, string> m = new HashMap<string, string>() my Map m can use the methods specific to HashMap, or not. I'm thinking it can't?
hatorade
ah, wait, no, my Map m from above must have the methods from HashMap.
hatorade
so basically the only perk of using Map in the 'interface sense' is that if i have a method that requires a map, i'm guaranteeing any type of map will work in this method. but if i used a hashmap, i'm saying the method only works with hashmaps. or, put another way, my method only uses methods defined in Map class but inherited by the other Classes which extend Map.
hatorade
in addition to the perk you mentioned above, where using List means I don't need to decide which type of List I want until runtime, whereas if the interface thing didn't exist I'd have to pick one before compiling and running
hatorade
I think you are correct in all your comments--exactly correct actually.
Bill K
And "Insertion Sort" isn't a method, it's a way of adding new records into the correctly sorted order. If you do that in an ArrayList, it has to block-move all the records past the one you are inserting down one for every single record added--a LinkedList, however, can just take a mid-collection insert extremely quickly due to it's nature.
Bill K
"As for your map comment below, Yes using the "Map" interface restricts you to only those methods unless you cast the collection back from Map to HashMap" isn't true right? Map<String, Object> map = new HashMap<String, Object>(); creates a Map map which has a HashMap under the hood, so I can use the HashMap methods. In a case where I will only EVER use HashMap methods, there is no difference between using Map or HashMap on the left side of the equals sign. Using Map is only beneficial where any type of Map can be passed into the method or I have a run-time choice, or something of the like
hatorade
Even if a map is a HashMap under the hood, it's still a "Map" until you cast it--you cannot access any HashMap methods without casting. Sometimes I visualize an interface as a shield with a bunch of holes in it that "Covers Up" the objects personality only letting some pieces through.
Bill K