adding a key value pair in java hashMap - java

I have a map which maps cost with position:
Map<Vector<Double>,Double> positionCost=new HashMap<Vector<Double>,Double>();
positions are Vectors of type double.
I am putting cost for each position by:
positionCost.put(position, newcost);
Now I have a vector where I save all the cost produced cost.add(newcost); for all the positions.
But there is one problem - the size of HashMap is not equal to the size of vector of costs.
System.out.println("no of particles"+" "+cost.size()+positionCost.size());
I am not able to figure out why.

The size of the positionCost Map won't be the same as the size of the cost Vector if you are adding the same position key more than once to the Map. In that case, the latter value associated with that key will overwrite the previous value that was associated that key, and the size of the Map will stay the same.
You should add a condition before adding to the map :
if (!positionCost.containsKey(position)) {
positionCost.put(position, newcost);
} else {
// the key already exists in the map. It might be a bug, or it might be
// a valid situation that you have to decide how to handle
}

Is it possible that you are adding a position-to-cost mapping to your map multiple times for the same position? I.e. the same Vector object? Or perhaps some position objects have the same hashcode? This will mean that you will replace an entry in your map at some point. The Vector object behaves differently - it merely appends the object. So I suggest printing the hashcode of the position object you are using as a key to debug.

This is because size of a hashmap depends on the number of keys.If keys are same,then it will count them as 1.So in your case the hashmap is counting the number of position.Hence the values are different

Related

Java Hashmap - Please explain how hash maps work

I am currently preparing for interviews, Java in particular.
A common question is to explain hash maps.
Every explanation says that in case there is more than a single value per key, the values are being linked listed to the bucket.
Now, in HashMap class, when we use put(), and the key is already in the map, the value is not being linked to the existing one (at list as I understand) but replacing it:
Map<String, Integer> map = new HashMap();
map.put("a", 1);
//map now have the pair ["a", 1]
map.put("a", 2);
//map now have the pair ["a", 2]
//And according to all hash maps tutorials, it should have been like: ["a", 1->2]
From the docs:
If the map previously contained a mapping for the key, the old value
is replaced.
What am I missing here? I am a little confused...
Thanks
You're confusing the behaviour of a Map with the implementation of a HashMap.
In a Map, there is only one value for a key -- if you put a new value for the same key, the old value will be replaced.
HashMaps are implemented using 'buckets' -- an array of cells of finite size, indexed by the hashCode of the key.
It's possible for two different keys to hash to the same bucket, a 'hash collision'. In case of a collision, one solution is to put the (key, value) pairs into a list, which is searched when getting a value from that bucket. This list is part of the internal implementation of the HashMap and is not visible to the user of the HashMap.
This is probably what you are thinking of.
Your basic understanding is correct: maps in general and hashmaps in particular only support one value per key. That value could be a list but that's something different. put("a", 2) will replace any value for key "a" that's already in the list.
So what are you missing?
Every explanation says that in case there is more than a single value per key, the values are being linked listed to the bucket.
Yes, that's basically the case (unless the list is replaced by a tree for efficiency reasons but let's ignore that here).
This is not about putting values for the same key into a list, however, but for the same bucket. Since keys could be mapped to the same bucket due to their hash code you'd need to handle that "collision".
Example:
Key "A" has a hash code of 65, key "P" has a hash code of 81 (assuming hashCode() just returns the ascii codes).
Let's assume our hashmap currently has 16 buckets. So when I put "A" into the map, which bucket does it go to? We calculate bucketIndex = hashCode % numBuckets (so 65 % 16) and we get the index 1 for the 2nd bucket.
Now we want to put "P" into the map. bucketIndex = hashCode % numBuckets also yields 1 (81 % 16) so the value for a different key goes to the same bucket at index 1.
To solve that a simple implementation is to use a linked list, i.e. the entry for "A" points to the next entry for "P" in the same bucket.
Any get("P") will then look for the bucket index first using the same calculation, so it gets 1. Then it iterates the list and calls equals() on each entry's key until it hits the one that matches (or none if none match).
in case there is more than a single value per key, the values are being linked listed to the bucket.
Maybe you mistake that with: Multiple keys can have the same hashCode value. (Collision)
For example let's consider 2 keys(key1, key2). Key1 references value1 and Key2 references value2.
If
hashcode(key1) = 1
hashcode(key2) = 1
The objects might have the same hashCode, but at the same time not be equal (a collision). In that situation both values will be put as List according to hashCode. Values will be retrieved by hashCode and than you'll get your value among that values by equals operation.

What if there is conflict of hashing of keys in ArrayMap or SparseArray?

I have read many blogs for array map and sparse array where every where I am getting that
ArrayMap contains two small array instead of one in a HashMap. The
first array (Hash-Array) contains the specified hash keys in sorted
order. The second array (Key Value Array) stores the keys and values
of the objects according to the first array. For reference below link is given
https://android.jlelse.eu/app-optimization-with-arraymap-sparsearray-in-android-c0b7de22541a
But no where I am getting that what happens if I have same hash code for two different keys in array map as in hash map it happens that in case having same key hash(collision) it appends the key value pair in linked list for a given bucket position for the next item.
Unlike the hashMap in ArrayMap when a hash collision occurs, instead of appending the key value pair in linked list for a given bucket position, for the next item it simply puts the value in next available position in second array. And for searching, when a hash collision occurs, it walk though the second array until finds the desired values.
Here it is described in provided doc:
When we fetch an item, a binary-search is done on the Hash-Array to find a matching hash the index and then directly return the key-value pair from the second array (Key Value Array). If the key in the second array (Key Value Array), doesn’t match then a linearly walk is done over the second array (Key Value Array) to resolve the collision.

Problems using HashMap

I'm trying to solve an analytic problem just for study data structures. My doubt is with the HashTable in Java.
I have a HashMap
HashMap<String, Integer> map = new HashMap<>();
And this HashMap has any fewer keys, but, some of these keys are duplicated.
map.put('k', 1);
map.put('k', 2);
And So on...
My question is when I am gonna remove a key to the HashMap. Some of these keys are duplicated too.
Let's see.
map.remove('k');
I suppose that in this case, it will remove all the values with the key 'k' or it just only remove the first it found.
What's going to happen in this case? I'm a little confused.
Thanks for your help!!
In HashMap (or HashTable) you can only have UNIQUE KEYS, you cannot have different values assigned to the same key. In your code you attempt put 2 different values with the same key:
map.put('k', 1);
map.put('k', 2);
Guess what, there will be no 2 entries, but only 1, the last, which will REPLACE previous one, since they have the same key - 'k'. Hence, map.remove('k'); will remove everything which is just one single entry, not two.
There are multiple things you are asking. Let's answer all of them.
HashTable is not the same as HashMap. However, hashTable is very similar to HashMap. The biggest difference between them is that in HashTable, every method is synchronized, which makes it extremely expensive to do a read/write. HashMap's methods are not synchronized. HashTable is more or less obsolete and people writing new code should avoid using a HashTable.
In a HashMap, keys are always unique. i.e., there cannot be 2 entries with the same key. In your example,
map.put('k', 1);
This will create an entry in the map whose key is 'k' and value is 1.
Then, you do
map.put('k', 2);
This will not create another entry with key 'k' and value 2. This will overwrite the value for the first entry itself. So, you will only have a singe entry for key 'k' whose value is now 2 (and not 1)
Now, I guess understanding remove() would be easy. When you do remove(key), it tries removing the only entry for that key.
In HashMap Keys will be unique , so it wont add multiple times of key K . when you remove key "K" , it will remove the unique key 'K' from the hashtable.
By definition a HashMap in Java stores all keys uniquely.
Simply, when we try to put more entries with the same key it will override the previously defined value for that key. Hence, when deleting a key after putting multiple values for that key means the key will no longer exist in the HashMap.
For more details you can read the documentation here.
use
map.putIfAbsent('k',2);
instead of
map.put('k', 2);

Iterating over hashmap in case of collision in Java

Let us say we have a collision but key values are different, so by definition Hashmap will create a linked list at that bucket and add the new key value pair as the next of existing key value entry.
My question is how do we iterate over the hashmap in this case ? Does the default iteration mechanism changes to actually retrieve all the key value pairs which collided and got stored in the same bucket location ?
There are no changes. It would iterate over like say bucket 0 i.e. every elements in bucket and then move to bucket 1 and so on. So there are no changes in the way it would iterate.

How key is mapped to value in a hasmap in java with O(1) get() method?

Consider an int array variable x[]. The variable X will have starting address reference. When array is accessed with index 2 that is x[2].then its memory location is calculated as
address of x[2] is starting addr + index * size of int.
ie. x[2]=x + 2*4.
But in case of hashmap how the memory address will be mapped internally.
By reading many previous posts I observed that HashMap uses a linked list to store the key value list. But if that is the case, then to find a key, it generates a hashcode then it will checks for equal hash code in list and retrieves the value..
This takes O(n) complexity.
If i am wrong in above observation Please correct me... I am a beginner.
Thank you
The traditional implementation of a HashMap is to use a function to generate a key, then use that key to access a value directly. Think of it as generating something that will translate into an array index. It does not look through the hashmap comparing element hashes to the generated hash; it generates the hash, and uses the hash to access an element directly.
What I think you're talking about is the case where two values in the HashMap generate the SAME key. THEN it uses a list of those, and has to look through them to determine which one it wants. But that's not O(n) where n is the number of elements in the HashMap, just O(m) where m is the number of elements with the same hash. Clearly the name of the game is to find a hash function where the generated hash is unique for all the elements, as much as is feasible.
--- edit to expand on the explanation ---
In your post, you state:
By reading many previous posts I observed that HashMap uses a linked
list to store the key value list.
This is wrong for the overall HashMap. For a HashMap to work reasonably, there must be a way to use the key to calculate a way to access the corresponding element directly, not by searching through all the values in the HashMap.
A "perfect" hash calculation would translate each possible key into hash value that was not calculated for any other key. This is usually not feasible, and so it is usually possible that two different keys will result in the same result from the hash calculation. In this case, the HashMap implementation could use a linked list of values, and would need to look through all such values to find the one that it was looking for. But this number is FAR less than the number of values in the overall HashMap.
You can make a hash where strings are the keys, and in which the first character of the string is converted to a number which is then used as an array index. As long as your strings all have different first characters, then accessing the value is a simple calc plus an array access -- O(1). Or you could add all the character values of the string indices together and take the last two (or three) digits, and THAT would be your hash calc. As long as the addition produced unique values for each index string, you don't ever have to look through a list; again, O(1).
And, in fact, as long as the hash calculation is approximately perfect, the lookup is still O(1) overall, because the limited number of times you have to look through a short list does not alter the overall efficiency.

Categories

Resources