Related
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>();
There is no difference between the objects; you have a HashMap<String, Object> in both cases. 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>. But the underlying object 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.
Example: Let's say I write this class:
class Foo {
private HashMap<String, Object> things;
private HashMap<String, Object> moreThings;
protected HashMap<String, Object> getThings() {
return this.things;
}
protected HashMap<String, Object> getMoreThings() {
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
The class has a couple of internal maps of string->object which it shares (via accessor methods) with subclasses. Let's say I write it with HashMaps to start with because I think that's the appropriate structure to use when writing the class.
Later, Mary writes code subclassing it. She has something she needs to do with both things and moreThings, so naturally she puts that in a common method, and she uses the same type I used on getThings/getMoreThings when defining her method:
class SpecialFoo extends Foo {
private void doSomething(HashMap<String, Object> t) {
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
// ...more...
}
Later, I decide that actually, it's better if I use TreeMap instead of HashMap in Foo. I update Foo, changing HashMap to TreeMap. Now, SpecialFoo doesn't compile anymore, because I've broken the contract: Foo used to say it provided HashMaps, but now it's providing TreeMaps instead. So we have to fix SpecialFoo now (and this kind of thing can ripple through a codebase).
Unless I had a really good reason for sharing that my implementation was using a HashMap (and that does happen), what I should have done was declare getThings and getMoreThings as just returning Map<String, Object> without being any more specific than that. In fact, barring a good reason to do something else, even within Foo I should probably declare things and moreThings as Map, not HashMap/TreeMap:
class Foo {
private Map<String, Object> things; // <== Changed
private Map<String, Object> moreThings; // <== Changed
protected Map<String, Object> getThings() { // <== Changed
return this.things;
}
protected Map<String, Object> getMoreThings() { // <== Changed
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
Note how I'm now using Map<String, Object> everywhere I can, only being specific when I create the actual objects.
If I had done that, then Mary would have done this:
class SpecialFoo extends Foo {
private void doSomething(Map<String, Object> t) { // <== Changed
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
}
...and changing Foo wouldn't have made SpecialFoo stop compiling.
Interfaces (and base classes) let us reveal only as much as is necessary, keeping our flexibility under the covers to make changes as appropriate. In general, we want to have our references be as basic as possible. If we don't need to know it's a HashMap, just call it a Map.
This isn't a blind rule, but in general, coding to the most general interface is going to be less brittle than coding to something more specific. If I'd remembered that, I wouldn't have created a Foo that set Mary up for failure with SpecialFoo. If Mary had remembered that, then even though I messed up Foo, she would have declared her private method with Map instead of HashMap and my changing Foo's contract wouldn't have impacted her code.
Sometimes you can't do that, sometimes you have to be specific. But unless you have a reason to be, err toward the least-specific interface.
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
Map has the following implementations:
HashMap Map m = new HashMap();
LinkedHashMap Map m = new LinkedHashMap();
Tree Map Map m = new TreeMap();
WeakHashMap Map m = new WeakHashMap();
Suppose you have created one method (this is just pseudocode).
public void HashMap getMap(){
return map;
}
Suppose your project requirements change:
The method should return map contents - Need to return HashMap.
The method should return map key's in insertion order - Need to change return type HashMap to LinkedHashMap.
The method should return map key's in sorted order - Need to change return type LinkedHashMap to TreeMap.
If your method returns specific classes instead of something that implements the Map interface, you have to change the return type of getMap() method each time.
But if you use the polymorphism feature of Java, and instead of returning specific classes, use the interface Map, it improves code reusability and reduces the impact of requirement changes.
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.
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.
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.
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.
Adding to the top voted answer and many ones above stressing the "more generic, better", I would like to dig a little bit more.
Map is the structure contract while HashMap is an implementation providing its own methods to deal with different real problems: how to calculate index, what is the capacity and how to increment it, how to insert, how to keep the index unique, etc.
Let's look into the source code:
In Map we have the method of containsKey(Object key):
boolean containsKey(Object key);
JavaDoc:
boolean java.util.Map.containsValue(Object value)
Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that (value==null ? v==null : value.equals(v)). This operation will probably require time linear in the map size for most implementations of the Map interface.
Parameters:value
value whose presence in this map is to betested
Returns:true
if this map maps one or more keys to the specified
valueThrows:
ClassCastException - if the value is of an inappropriate type for this map (optional)
NullPointerException - if the specified value is null and this map does not permit null values (optional)
It requires its implementations to implement it, but the "how to" is at its freedom, only to ensure it returns correct.
In HashMap:
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
It turns out that HashMap uses hashcode to test if this map contains the key. So it has the benefit of hash algorithm.
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);
Map is interface and Hashmap is a class that implements Map Interface
Map is the Interface and Hashmap is the class that implements that.
So in this implementation you create the same objects
HashMap is an implementation of Map so it's quite the same but has "clone()" method as i see in reference guide))
HashMap<String, Object> map1 = new HashMap<String, Object>();
Map<String, Object> map2 = new HashMap<String, Object>();
First of all Map is an interface it has different implementation like - HashMap, TreeHashMap, LinkedHashMap etc. Interface works like a super class for the implementing class. So according to OOP's rule any concrete class that implements Map is a Map also. That means we can assign/put any HashMap type variable to a Map type variable without any type of casting.
In this case we can assign map1 to map2 without any casting or any losing of data -
map2 = map1
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java - HashMap vs Map objects
What's the difference between :
Map <String,Integer>myMap = new HashMap<String,Integer>();
VS
HashMap <String,Integer> map = new HashMap<String,Integer>();
Regards,Ron
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...
Also 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..
Difference is:
when you use Map as a type you can switch implemenation (HashMap) to other!
its a good thing!
EDIT: read this - What does it mean to "program to an interface"?
One additional point.
Declaring the variable as a Map prevents you from using the clone() method provided by the HashMap class.
so, if you use:
Map <String,Integer>myMap = new HashMap<String,Integer>();
then you can't use:
Map<String,Integer> myMap2 = myMap.clone();
Other than that, they're pretty interchangeable.
I have a basic question about using the "Best Practices" in coding. (I'm using Java, but the question is general to OOP.) When writing method's for a class that are intended to be used in the long run, is it best to leave the return object with or without generics?
To be specific in my case, I'm returning a Map<String, Integer> with the method. Should I specify this in the return statement, or should I simply return a Map?
It is best to use generics whenever possible. It will help avoid runtime exceptions, and it won't force the people using your code to do a bunch of ugly type casting. For example, if you use the following signature:
Map<String, Integer> getMap();
... then the consuming code might look like this:
Map<String, Integer> map = getMap();
Integer val = map.get(key);
... but if you use a signature like this:
Map getMap();
... the consuming code might look like this:
Map<String, Integer> map = (Map<String, Integer)getMap();
Integer val = map.get(key);
By using generics, not only do you save that (Map<String, Integer>) cast, but in the event that you change getMap to actually return a Map<String, Object>, you will get a compile-time error (which is easy to catch and fix), rather than possibly getting an exception when you call map.get(key) and the JRE tries to do an automatic cast of some random Object into an Integer.
You should definitely return a Map<String, Integer> instead of a plain Map if it makes sense in your method, as this will make it easier for others to use said method - after getting the Map<String, Integer> they will be able to retrieve String keys and Integer values without having to cast them from a generic Object every time (this also makes it a little more typesafe as this way they will know what the keys and values are without even reading the javadoc for your method).
So in short, definitely, return generics.
If you are returning a collection, you should include the generic type that is contained by the collection. For example:
public Map<String, Blammo> getBlammoMap(...)
is (IMHO) preferred to
public Map getBlammoMap(...)
Because it
Limits the options of a bad cast (i.e. kapowMap = (Map<String, Kapow> getBlammoMap()).
Tells the consumer what the method is actually returning.
If the method is clearly intended to work with a certain type (i.e. only String), then it's ok to return a List<String>. If the method is generic taking a type parameter T, you can return List<T>.
I would not simply return a Map, because usually it causes confusion and more boiler-plate code to convert to the desired type.
In general, your type parameters, both input and output, should capture the level of specificity of the precise function. In functional programming, they go so far as to say "the types are the documentation." If I were to see Map foo(Arg args) I would think that foo is in no way concerned with the types in the Map it returns, but somehow relies on Args for something." If I were to see Map<T,String> foo(T t, Arg arg) or Map<T, U> foo(T t, U u) I would think "OK, foo produces a Map based on the type of its t and with a String produced by Arg (or by the U from u)."
In terms of preference, clearly you want to be as clear as possible to the future programmer (yourself or others). Just as returning Map without type-params is obscure, so too would returning Map<String, Integer> might be overly restrictive (and thus misleading) if your foo would work equally well with, say, Map<String, Long>
I believe that more specific, the better. If your method is return a map that always has Strings as the key, and Integers as the value, then definitely use the Map has the return type. That way, any calling code knows exactly what they're getting. If the return type was just Map, then the calling code would have no idea what the class the keys and values are (Other than Object).
In general, you should probably always specify paramerize Maps, Lists, etc., so it's known exactly what it contains. This is very helpful when iterating over them and you can use a java foreach.
for (String currKey : myMap.keySet())
{
System.out.println("curr Key: " + currKey + " curr Value: " + myMap.get(currKey));
}
This eliminates any extra iterators or casting.
Ho-ho-ho! A pretty New Year question.
You generally must (MUST) return a proper generic Map<Whatever, YouNeed>. It may sound crazy, but as soon as you use any generic type without type parameters, you're getting into trouble.
The trouble will be as follows: raw types, being used in the code, change the way methods (even seemingly non-related ones) are resolved. Find a presentation by Joshua Bloch and Bill Pugh called "Java Puzzlers: Scraping the Bottom of the Barrel" for details whle I'm preparing an example :) The video with details is at http://www.parleys.com/#id=2168&st=5 (you may want to scroll to slide 44, 5. "Glommer Pile")
So here's an example:
/**
* (c) (as far as I know) Joshua Bloch and Bill Pugh, 2010
*/
public class Glommer<T> {
String glom(Collection<?> objs) {
String result = "";
for (Object o : objs) result += o;
return result;
}
int glom(List<Integer> ints) {
int result = 0;
for (int i : ints) result += i;
return result;
}
public static void main(String args[]) {
List<String> strings = Arrays.asList("1", "2", "3");
System.out.println(new Glommer().glom(strings));
}
}
Question is, whether it
prints 6
prints 123
throws an exception,
or does something else.
Try to guess. Then compile (yes it compiles) and see what happens.
Now that does not apply to your case. But having a habit of always specifying the type, even if it will be just Map<?,?>, is extremely helpful. You won't lose.
The obligatory Java Generics FAQ link
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>();
There is no difference between the objects; you have a HashMap<String, Object> in both cases. 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>. But the underlying object 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.
Example: Let's say I write this class:
class Foo {
private HashMap<String, Object> things;
private HashMap<String, Object> moreThings;
protected HashMap<String, Object> getThings() {
return this.things;
}
protected HashMap<String, Object> getMoreThings() {
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
The class has a couple of internal maps of string->object which it shares (via accessor methods) with subclasses. Let's say I write it with HashMaps to start with because I think that's the appropriate structure to use when writing the class.
Later, Mary writes code subclassing it. She has something she needs to do with both things and moreThings, so naturally she puts that in a common method, and she uses the same type I used on getThings/getMoreThings when defining her method:
class SpecialFoo extends Foo {
private void doSomething(HashMap<String, Object> t) {
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
// ...more...
}
Later, I decide that actually, it's better if I use TreeMap instead of HashMap in Foo. I update Foo, changing HashMap to TreeMap. Now, SpecialFoo doesn't compile anymore, because I've broken the contract: Foo used to say it provided HashMaps, but now it's providing TreeMaps instead. So we have to fix SpecialFoo now (and this kind of thing can ripple through a codebase).
Unless I had a really good reason for sharing that my implementation was using a HashMap (and that does happen), what I should have done was declare getThings and getMoreThings as just returning Map<String, Object> without being any more specific than that. In fact, barring a good reason to do something else, even within Foo I should probably declare things and moreThings as Map, not HashMap/TreeMap:
class Foo {
private Map<String, Object> things; // <== Changed
private Map<String, Object> moreThings; // <== Changed
protected Map<String, Object> getThings() { // <== Changed
return this.things;
}
protected Map<String, Object> getMoreThings() { // <== Changed
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
Note how I'm now using Map<String, Object> everywhere I can, only being specific when I create the actual objects.
If I had done that, then Mary would have done this:
class SpecialFoo extends Foo {
private void doSomething(Map<String, Object> t) { // <== Changed
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
}
...and changing Foo wouldn't have made SpecialFoo stop compiling.
Interfaces (and base classes) let us reveal only as much as is necessary, keeping our flexibility under the covers to make changes as appropriate. In general, we want to have our references be as basic as possible. If we don't need to know it's a HashMap, just call it a Map.
This isn't a blind rule, but in general, coding to the most general interface is going to be less brittle than coding to something more specific. If I'd remembered that, I wouldn't have created a Foo that set Mary up for failure with SpecialFoo. If Mary had remembered that, then even though I messed up Foo, she would have declared her private method with Map instead of HashMap and my changing Foo's contract wouldn't have impacted her code.
Sometimes you can't do that, sometimes you have to be specific. But unless you have a reason to be, err toward the least-specific interface.
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
Map has the following implementations:
HashMap Map m = new HashMap();
LinkedHashMap Map m = new LinkedHashMap();
Tree Map Map m = new TreeMap();
WeakHashMap Map m = new WeakHashMap();
Suppose you have created one method (this is just pseudocode).
public void HashMap getMap(){
return map;
}
Suppose your project requirements change:
The method should return map contents - Need to return HashMap.
The method should return map key's in insertion order - Need to change return type HashMap to LinkedHashMap.
The method should return map key's in sorted order - Need to change return type LinkedHashMap to TreeMap.
If your method returns specific classes instead of something that implements the Map interface, you have to change the return type of getMap() method each time.
But if you use the polymorphism feature of Java, and instead of returning specific classes, use the interface Map, it improves code reusability and reduces the impact of requirement changes.
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.
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.
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.
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.
Adding to the top voted answer and many ones above stressing the "more generic, better", I would like to dig a little bit more.
Map is the structure contract while HashMap is an implementation providing its own methods to deal with different real problems: how to calculate index, what is the capacity and how to increment it, how to insert, how to keep the index unique, etc.
Let's look into the source code:
In Map we have the method of containsKey(Object key):
boolean containsKey(Object key);
JavaDoc:
boolean java.util.Map.containsValue(Object value)
Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that (value==null ? v==null : value.equals(v)). This operation will probably require time linear in the map size for most implementations of the Map interface.
Parameters:value
value whose presence in this map is to betested
Returns:true
if this map maps one or more keys to the specified
valueThrows:
ClassCastException - if the value is of an inappropriate type for this map (optional)
NullPointerException - if the specified value is null and this map does not permit null values (optional)
It requires its implementations to implement it, but the "how to" is at its freedom, only to ensure it returns correct.
In HashMap:
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
It turns out that HashMap uses hashcode to test if this map contains the key. So it has the benefit of hash algorithm.
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);
Map is interface and Hashmap is a class that implements Map Interface
Map is the Interface and Hashmap is the class that implements that.
So in this implementation you create the same objects
HashMap is an implementation of Map so it's quite the same but has "clone()" method as i see in reference guide))
HashMap<String, Object> map1 = new HashMap<String, Object>();
Map<String, Object> map2 = new HashMap<String, Object>();
First of all Map is an interface it has different implementation like - HashMap, TreeHashMap, LinkedHashMap etc. Interface works like a super class for the implementing class. So according to OOP's rule any concrete class that implements Map is a Map also. That means we can assign/put any HashMap type variable to a Map type variable without any type of casting.
In this case we can assign map1 to map2 without any casting or any losing of data -
map2 = map1
So I have two questions about HashMaps in Java:
What is the correct way to initialize a HashMap? I think it might be best in my situation to use:
HashMap x = new HashMap();
But Eclipse keeps suggesting that I use:
HashMap<something, something> map = new HashMap();
Which is better?
Can a HashMap hold different types of objects/data types as values? For example, would this work and be OK:
map.put("one", 1);
map.put("two", {1, 2});
map.put("three", "hello");
In the first put(), I want an int as a value, in the second an int[], and third a string. Is this okay to do in Java with HashMaps? Also, is it okay to store a HashMap as a value within a HashMap?
It really depends on what kind of type safety you need. The non-generic way of doing it is best done as:
Map x = new HashMap();
Note that x is typed as a Map. this makes it much easier to change implementations (to a TreeMap or a LinkedHashMap) in the future.
You can use generics to ensure a certain level of type safety:
Map<String, Object> x = new HashMap<String, Object>();
In Java 7 and later you can do
Map<String, Object> x = new HashMap<>();
The above, while more verbose, avoids compiler warnings. In this case the content of the HashMap can be any Object, so that can be Integer, int[], etc. which is what you are doing.
If you are still using Java 6, Guava Libraries (although it is easy enough to do yourself) has a method called newHashMap() which avoids the need to duplicate the generic typing information when you do a new. It infers the type from the variable declaration (this is a Java feature not available on constructors prior to Java 7).
By the way, when you add an int or other primitive, Java is autoboxing it. That means that the code is equivalent to:
x.put("one", Integer.valueOf(1));
You can certainly put a HashMap as a value in another HashMap, but I think there are issues if you do it recursively (that is put the HashMap as a value in itself).
This is a change made with Java 1.5. What you list first is the old way, the second is the new way.
By using HashMap you can do things like:
HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();
....
Doohickey result = ourMap.get("bob");
If you didn't have the types on the map, you'd have to do this:
Doohickey result = (Doohickey) ourMap.get("bob");
It's really very useful. It helps you catch bugs and avoid writing all sorts of extra casts. It was one of my favorite features of 1.5 (and newer).
You can still put multiple things in the map, just specify it as Map, then you can put any object in (a String, another Map, and Integer, and three MyObjects if you are so inclined).
Eclipse is recommending that you declare the type of the HashMap because that enforces some type safety. Of course, it sounds like you're trying to avoid type safety from your second part.
If you want to do the latter, try declaring map as HashMap<String,Object>.
The way you're writing it is equivalent to
HashMap<Object, Object> map = new HashMap<Object, Object>();
What goes inside the brackets is you communicating to the compiler what you're going to put in the HashMap so that it can do error checking for you. If Object, Object is what you actually want (probably not) you should explicitly declare it. In general you should be as explicit as you can with the declaration to facilitate error checking by the compiler. What you've described should probably be declared like this:
HashMap<String, Object> map = new HashMap<String, Object>();
That way you at least declare that your keys are going to be strings, but your values can be anything. Just remember to use a cast when you get a value back out.
The 2nd one is using generics which came in with Java 1.5. It will reduce the number of casts in your code & can help you catch errors at compiletime instead of runtime. That said, it depends on what you are coding. A quick & dirty map to hold a few objects of various types doesn't need generics. But if the map is holding objects all descending from a type other than Object, it can be worth it.
The prior poster is incorrect about the array in a map. An array is actually an object, so it is a valid value.
Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object
Also, since HashMap is an object, it can also be a value in a HashMap.
A HashMap can hold any object as a value, even if it is another HashMap. Eclipse is suggesting that you declare the types because that is the recommended practice for Collections. under Java 5. You are free to ignore Eclipse's suggestions.
Under Java 5, an int (or any primitive type) will be autoboxed into an Integer (or other corresponding type) when you add it to a collection. Be careful with this though, as there are some catches to using autoboxing.
Eclipse is suggesting you to define generic type so that you can have type safety. You can write
Map m = new HashMap();
which does not ensure type safety but following will ensure type safety
Map<Object,Object> = new HashMap<Object,Object>();
The Object can be any type such as String, Integer etc.
Map.of literals
As of Java 9, there is yet another way to instantiate a Map. You can create an unmodifiable map from zero, one, or several pairs of objects in a single-line of code. This is quite convenient in many situations.
For an empty Map that cannot be modified, call Map.of(). Why would you want an empty set that cannot be changed? One common case is to avoid returning a NULL where you have no valid content.
For a single key-value pair, call Map.of( myKey , myValue ). For example, Map.of( "favorite_color" , "purple" ).
For multiple key-value pairs, use a series of key-value pairs. ``Map.of( "favorite_foreground_color" , "purple" , "favorite_background_color" , "cream" )`.
If those pairs are difficult to read, you may want to use Map.of and pass Map.Entry objects.
Note that we get back an object of the Map interface. We do not know the underlying concrete class used to make our object. Indeed, the Java team is free to used different concrete classes for different data, or to vary the class in future releases of Java.
The rules discussed in other Answers still apply here, with regard to type-safety. You declare your intended types, and your passed objects must comply. If you want values of various types, use Object.
Map< String , Color > preferences = Map.of( "favorite_color" , Color.BLUE ) ;
In answer to your second question: Yes a HashMap can hold different types of objects. Whether that's a good idea or not depends on the problem you're trying to solve.
That said, your example won't work. The int value is not an Object. You have to use the Integer wrapper class to store an int value in a HashMap