I have instantiated my HashMap like this:
Map<String, Integer> myHashMap = new HashMap<String, Integer>();
The datatype of the Key
is String, so when I try to insert a new key-value pair in the map keeping the Key
as Integer, it throws an error.
myHashMap.put(1L, "value");
That means in the put method they have restricted the datatype of the Key
. But while fetching the value from the map using the get
method it is not checking for the datatype of the Key
. So if I write something like this, it doesn't give a compilation error.
myHashMap.get(1L);
I checked the get
method in the Java Map interface and its parameter type is Object
, so that's why it is allowing any Object as the put method argument.
V get(Object key)
Is there a way I can restrict the datatype which I pass as an argument in the get
method?
The argument that I pass should have the same datatype as the datatype of the Key
which I use while instantiating my hashmap.
HashMap stores key, value pairs and it does not allow duplicate keys. If the key is duplicate then the old key is replaced with the new value.
If you have to avoid duplicates you also know we have to use Set from the collections. You can do like Map<set<id>,sObject> newMap = Map<set<id>,sObject>(); Please take it as a general solution which you can modify as per your requirement.
If two keys are the same ( equals() returns true when you compare them), their hashCode() method must return the same number. If keys violate this, then keys that are equal might be stored in different buckets, and the hashmap would not be able to find key-value pairs (because it's going to look in the same bucket).
It is designed that way, since during the get operation only the equals
and hashCode
is used to determine the object to be returned. The implementation of the get
method does not check for the type of the Object used as the key.
In your example you are trying to get the value by passing a long like myHashMap.get(1L);
, firstly the hash code of the object Long
having the value 1L
will be used to determine the bucket from which to look for. Next the equals
method of the key is used to find out the exact entry of the map from which to return the value. And in a well-defined equals
method there is always a check for the type:
public boolean equals(Object obj) {
if (obj instanceof Long) { //here type is checked
return value == ((Long)obj).longValue();
}
return false;
}
So if the types are not equal, the equals
method returns false
and hence get
also will return null
.
In some cases such as when using List
as a key, it may happen that you put an item in the map using an instance of say an ArrayList
but you can successfully retrieve the same value with an instance of an LinkedList
. As both implement the List
interface.
Map<List<String>, String> myHashMap = new HashMap<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
myHashMap.put(arrayList, "foo");
System.out.println(myHashMap.get(linkedList));
The above code will output in the console foo
.
Here although the implementations are different but if you examine the equals
method of ArrayList
, it is only checking if the type is a List
:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) { //checking type of super interface
return false;
}
...
}
The same is true for LinkedList
.
I think if it is very important in a project that we control type in HashMap, we could extend HashMap and force using this class instead of HashMap like the below code.
We have all HashMap capabilities, and we should just use the getValue method instead of the get method.
import java.util.HashMap;
public class MyHashMap<K,V> extends HashMap<K,V> {
public V getValue(K key) {
return super.get(key);
}
}
Test class:
public class Test {
public static void main(String[] args) {
MyHashMap<String,Integer> map = new MyHashMap();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With