How hashmap works with Integer as keys [duplicate] - java

This question already has answers here:
HashMap is already sorted by key?
(3 answers)
Closed 8 years ago.
Map<Integer,String> m1 = new HashMap<>();
m1.put(5, "gfd");
m1.put(1,"sandy");
m1.put(3, "abc");
m1.put(2, "def");
m1.put(1, "ijk");
m1.put(10, "bcd");
m1.put(0, "ssdfsd");
When I Print the map, the output is {0=ssdfsd, 1=ijk, 2=def, 3=abc, 5=gfd, 10=bcd}.
But, how the output is in sorted order even though I have used HashMap()??

You can easily see this in the implementation. If you look into the source of HashMap.put(), you can see that the hash table index of the object is determined like this:
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
The methods hash() and indexFor() only ensure that there are not too many collisions of hash values and they don't exceed the length of the hash table.
Now if you take a look at Integer.hashCode(), you'll see that the hash is the integer itself:
public int hashCode() {
return value;
}
So the integer which has the value 0 ends up in index 0 of the hash table and so on. At least as long as the hash table is big enough.
The toString() method of HashMap iterates over the hash table and the elements in each index of the hash table. So in your case the order is preserved.
As others mentioned correctly, this behavior is not ensured by implementations of Map. It just works in this special case.

A Map provides you with the interface of storing and retrieving objects into a map with a key attached to them.
What each implementation does internally is fully up to it, including in which order the key/value pairs are stored in the internal structure. See #Seshoumaro's answer for the quote from the javadoc.
HashMap hashes the key (which is an Integer in this case) and uses that hash as an array index. Since the hashCode for Integer is fairly simple to write yourself, it's not surprising that the array indices for each one are in the same order as the key itself.
What all that means is: you shouldnt be surprised that the HashMap is acting this way.

The HashMap provides no guarantee as to the order of the items stored. It may even be in order in some cases. Taken from the javadoc:
This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
So it's working as intended. If you're curious as to why this particular example is placed in order, you could check out the source code itself.

Its not just restricted to keys of Integers you may obtain the same with Strings at times.
It just so happens to be at times and you would find numerous instances of the same.
As suggested by others HashMap never guarantees the insertion order while fetching.Since the official doc says to not rely you might find occasions when it would not retain the order so better code likewise.
See this for more

Related

Does a java hashmap bucket really contain a list?

Ive always been certain that a 'bucket' in a java hash map contains either a linked list or a Tree of some kind, indeed you can read in many places on the web how the bucket holds this list then iterates over the entries using the equals function to find entries that are stored in the same bucket (ie have the same key), bearing this in mind, can someone explain why the following, trivial code doesnt work as expected :-
private class MyString {
String internalString;
MyString(String string) {
internalString = string;
}
#Override
public int hashCode() {
return internalString.length(); // rubbish hashcode but perfectly legal
}
}
...
Map<MyString, String> map = new HashMap<>();
map.put(new MyString("key1"), "val1");
map.put(new MyString("key2"), "val2");
String retVal = map.get(new MyString("key1"));
System.out.println("Val returned = "+retVal);
In this example I would have expected the two map entries to be in the list in the (same) bucket and for retVal to equal "val1", however it equals null?
A quick debug shows why, the bucket does not contain a list at all just a single entry.....
I thought i was going mad until I read this on the baeldung website (https://www.baeldung.com/java-map-duplicate-keys)
...However, none of the existing Java core Map implementations allow a Map to handle multiple values for a single key.
What is going on, does a bucket in a hash map contain a list or not ?
Does a java hashmap bucket really contain a list?
It depends.
For older implementations (Java 7 and earlier), yes it really does contain list. (It is a singly linked list of an internal Node type.)
For newer implementations (Java 8 and later), it can contain either a list or a binary tree, depending on how many entries hash to the particular bucket. If the number is small, a singly linked list is used. If the number is larger than a hard-coded threshold (8 in Java 8), then the HashMap converts the list to a balanced binary tree ... so that bucket searches are O(logN) instead of O(N). This mitigates the effects of a hash code function that generates a lot of collisions (or one where this can be made to occur by choosing keys in a particular way.)
If you want to learn more about how HashMap works, read the source code. (It is well commented, and the comments explain the rationale as well as the nitty-gritty how does it work stuff. It is worse the time ... if you are interested in this kind of thing.)
However, none of the existing Java core Map implementations allow a Map to handle multiple values for a single key.
That is something else entirely. That is about multiple values for a key rather than multiple keys in a bucket.
The article is correct. And this doesn't contradict my "a bucket contains a list or tree" statement.
Put simply, a HashMap bucket can contain multiple key / value pairs, where the keys are all different.
The only point on which I would fault the quoted text is that it seems to imply that it is implementations of Map that have the one value per key restriction. In reality, it is the Map API itself that imposes this restriction ... unless you use (say) a List as the map's value type.

How to maintain uniqueness of key in hashmap internally [duplicate]

This question already has answers here:
How does a hash table work?
(17 answers)
Closed 1 year ago.
Everyone know hashmap contain unique key. But i want know how it maintain uniqueness?
Suppose we inserted 100 data into the hashmap, After that we insert duplicate key and value in the same hashmap. I know it will override the value. But i want to know it will check all the previous keys which is already stored inside the hashmap then will override new key.
Or if it check previous all keys everytime then it will take more time . So please tell me the correct answer.
You need to know the internal representation of the HashMap.
Actually it is an array of list of key value items, graphically we can represent it as you can see below:
bucket
position
--------
0 NULL
1 --> (K1, V1) --> (K47, V47)
2 NULL
3 NULL
...
54 --> (K89, V89)
...
When you perform a put operation put(key, value) first the code retrieve the hashCode of the key. This value with a module operation is needed to search on the list on the specific bucket.
Then it performs a search element by element on that list performing an equals method to check if the key is already present or not.
If the key is present it replace only the value, if not it will add a new couple key, value at the end of the list.
The pseudo code of the HashMap is similar to the following:
public HashMap {
private List<List<KeyValue<K, V>>> keyValuesBuckets;
public void put(K key, V value) {
int hash = key.hashCode();
int bucketPosition = hash % keyValuesBuckets.size();
for (KeyValue kv : keyValuesBuckets.get(bucketPosition)) {
if (kv.getKey().equals(key)) {
// Key is present change the value and exit
kv.setValue(value);
return;
}
}
// Key is not present
keyValuesBuckets.get(bucketPosition).add(new KeyValue(key, value));
}
Note that the code is not the real code. There is no check on the null values for example, but it gives you the idea on how the equality is checked using both hashCode and equals methods.
To have a more in depth details on how it works start from the definition of [hashCode][1]:
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.
and [equals][2]
In the javadoc you can find the contract that equals and hashCode must supply so that a class can be used as a key in a HashMap:
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
[1]: https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--
[2]: https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
Take a look at the following image taken from here (https://www.bigocheatsheet.com/)
Hash collections have a O(1) insertion complexity meaning that the operation does not depend on how many data points are already present in the data structure.
As the name suggests keys are hashed into buckets.
If you want to look up a values for key a the key is taken and a hash function employed mapping the value to a specific memory location. There is no need to look up any other value.
The exception are hash collisions which are bound to happen due to dimensionality reduction. After employing the has function, different keys max resolve to the same hash and thus land in the same bucket. In this case other means of checks have to take place (this is the reason why you always have to overwrite hashcode and equals)
Further information about this can be found here: https://stackoverflow.com/a/19691998/3244464

O(1) method of getting K using V with a java hashmap? [duplicate]

This question already has answers here:
Bidirectional Map
(9 answers)
Closed 4 years ago.
In Java 8 is there an O(1) method of getting the K by using V for a hashmap? Would I have to use two hashmaps(KV and VK) and if so would that defeat the purpose of having O(1)?
For context, I am trying to find the most efficient way of getting (String userName, Integer userIdentifier) using either value or key.
As a general note - there's a hidden assumption here that the values are also unique. Otherwise, you won't be able to retrieve a single key by a value, but a list of keys, although even if you take that into consideration it won't change the answer much. Additionally, with your usecase of userName and userId, this may be a moot point altogether.
As you alluded, a simple HashMap won't be enough - that would mean you'd need to iterate over the entries to find an entry with a specific key, which would be an O(n) operation.
Using two HashMaps (name to id and id to name) is a good approach. While this would mean you'd have to perform two operations instead of one each time you add/remove/modify a user, it won't affect the order of magnitude (since you're still performing a constant number of constant-time operations), and you'll retain the O(1) insertion time.
This is in fact a pretty common approach, and if you can introduce third-party libraries to your project, there are pretty solid implementations of this concept out there, like Apache Commons Collections' DualHashBidiMap.
Maps are meant for searching by key, so you won't get O(1) lookup by value, unless you use a second map.
What serves your use case is a BiMap avaliable from Google Guava
BiMap<String, Integer> nameidmap = HashBiMap.create();
Integer id = nameidmap.get("name");
String name = nameidmap.inverse().get(12345);
Internally Guava also maintains two hash tables, but it does the heavy lifting of keeping the two maps in sync. You can find full Javadoc for Bimap here.
If you want to use only single hashmap, you can do
map.put(key, value) and then map.put(value, key)
Assuming values are unique and also not equal to any key

HashMaps in Java - Indexed or not

The question:
Is the HashMap(Map) we use in java indexed or not ? And if it is indexed, could you please explain it briefly ?
Try using LinkedHashMap instead of HashMap, which orders elements by insertion. Reference: Java - get index of key in HashMap?
HashMaps contain key&value pairs. Every key may only exist once.
You cannot get values using an index, but need to use the method
HashMap.get()
A decent tutorial can be found here:
https://beginnersbook.com/2013/12/hashmap-in-java-with-example/
HashMaps are an implementation of a Hash Table. The hashCode() function, that all Classes inherit from the Object class, is used to, ideally, produce a unique integer. The hashCode integer is used to map an object value to a location where, assuming low collisions, search time is O(1). If the hashCode() function is poor and produces the same value for many keys within the HashMap, search time may degrade (The HashMap will rehash itself once the number of entries in the Map exceeds the product of the load factor and the current capacity).
In a sense, HashMaps are indexed and that is what enables their good performance. However, they are not indexed in the manner you could obtain an item from index and the HashMap class will not ensure that order is retained; you will need to use a LinkedHashMap.

HashMap put method

I'm having some trouble when using .put(Integer, String) in Java.
To my understanding, when a collision happens the HashMap asks whether the to value are the same with .equals(Object) and if they are not the two values are stored in a LinkedList. Nevertheless, size() is 1 and the hash iterator only shows one result, the last one.
Apart form this, java HashMap API states:put
public V put(K key, V value)
Associates the specified value with the specified key in this map. If
the map previously contained a mapping for the key, the old value is
replaced.
THIS IS NOT WHAT I HAVE READ EVERYWHERE.
Thoughts?
public class HashProblema {
public static void main(String[] args) {
HashMap<Integer, String> hash= new HashMap();
hash.put(1, "sdaaaar");
hash.put(1, "bjbh");
System.out.println(hash.size());
for (Object value : hash.values()) {
System.out.println(value);
}
}
}
The output is -:
1
bjbh
Since the mapping for the key exist, it is replaced and the size remains 1 only.
The value gets over written by the new key..the size remains one and the value gets changed..This is how it works, as key values are always unique..You can't map multiple values on 1 key.
The API is the definitive reference and that is what you must believe.
A collision occurs when the hash of of a key already exists in the HashMap. Then the values of the keys are compared, and if they are the different, the entries are placed in a linked list. If the keys are the same, then the old key-value in the HashMap is overwritten.
API documentation should normally be treated as authoritative unless there is very good reason to doubt its accuracy.
You should almost certainly ignore any claim that doesn't flag itself as 'knowingly' at odds with documentation and provide a testable evidence.
I humbly suggest you might be confused about the role of a linked 'collision' list. As it happens HashMap in Java uses a linked-list to store multiple values for which the hash-code of the key is placed in the same 'bucket' as one or more other keys.
A HashMap in Java will always store a Key-Value-Pair. There are no linked lists involved. What you are describing is the general idea of a hash map (often taught in computer science class), but the implementation in Java is different. Here, you will always have one value per key only (the last one you put in that place).
However, you are free to define a HashMap that contains List objects. Though, you have to keep track of duplicates and collisions on your own then

Categories

Resources