Java for Humans {Data Structures : HashMaps}

Lincoln W Daniel
Jan 19, 2016 · 6 min read
View Table of Contents | Download Supporting Code | Subscribe to ModernNerd Youtube Channel for Coding Videos | By Lincoln W Daniel

Arrays let you collect a fixed amount of elements in one data structure, and Lists can do the same but without bounds. The only thing they both don’t allow you to do is store objects and retrieve them by a specific, unique key. This is where the HashMap comes into play. If we want to make a dictionary of all the words in the English language alongside their meanings, our best bet would be to use a HashMap.

Why HashMaps are Important & Useful

Maps in Java are powerful tools, and the HashMap is perhaps one of the most powerful of them all. The HashMap class, an implementation of the Map interface, takes the best ideas of the List interface, combines it with the prowess of arrays, and gives us a tool to collect key-value pairs in one place. Elements of a HashMap are stored as pairs and it insures that no two pairs can have the same key, therefore maintaining the unique property of each of element.

The HashMap class provided to us by Java allows us to collect values of the same type and store them with unique keys. In the background, a HashMap uses arrays to store its elements. However, we don’t care about how it works in the background because all of the hard work is encapsulated. The HashMap class provides us methods to put a pair in the map, replace a pair’s value by key, remove a pair by key, check for the existence of a key, and clear the map like we do with a list.

A key can be of any datatype, but its important to remember that String keys are case sensitive. To ensure that all keys in the HashMap are unique, the map has a hash() method behind the scenes to hash all keys added to it. When you call the put() instance method, the key you provide is hashed to a unique hash string value and when you call the get() or containsKey() instance methods, the key you provide is hashed the same way. The hash that results is used to find a pair in the map that has a key with a matching hash. If a pair is found, the pair will be returned if you called get(), a boolean value of true will be returned if you called containsKey(), or its value will be updated with the new value if you called put(). Let’s try to make a dictionary of some of our favorite Java terms to help us study later:

HashMap dictionary = new HashMap();
dictionary.put("Variable", "Used to store a single value for later use.");
dictionary.put("String", "A class for representing character strings.");
dictionary.put("double", "A primitive datatype for representing floating point numbers.");
dictionary.put("Double", "A class for wrapping a double in an Object with convenient methods.");
dictionary.put(0, "The number zero. The first index in arrays and the first position on lists.");
dictionary.put("zero", 0);
System.out.println("Elements in map: " + dictionary.size());
//prints "Elements in map: 6"

We’ve added six pairs to our dictionary HashMap instance — five String keys and one integer key. Let’s print out the value of some of the pairs by key:

System.out.println("double: " + dictionary.get("double"));
Object meaningOfDouble = dictionary.get("Double");
Object meaningOf0 = dictionary.get(0);
System.out.println("Double: " + meaningOfDouble);
System.out.println("0: " + meaningOf0);
System.out.println("zero: " + dictionary.get("zero"));
/*Prints
double: A primitive datatype for representing floating point numbers.
Double: A class for wrapping a double in an Object with convenient methods.
0: The number zero. The first index in arrays and the first position on lists.
zero: 0
*/

Notice that when we retrieved the value of the elements of our dictionary, they were returned as instances of the Object class. This is because if we do not specify which type of data our keys and values can be, Java makes Object the type of the HashMap’s keys and values because every class is a subclass of the Object class; the Integer, Double, Long, and other wrapper classes are provided by Java to wrap primitive datatypes in objects because primitives are not objects. This is why we were able to have both String and int keys and values. This is okay sometimes, but we should usually specify exactly what type of data we want to store in our data structures to avoid unexpected situations that can result from ambiguity. To specify the type of our map, we do the same thing we did to initialize our LinkedList instance in the LinkedLists chapter: place the type’s class name inside of a set of opening and closing arrows <>. We could make our HashMap instance accept, String keys and Integer values, but doesn’t make much sense for our dictionary .Let’s remake our dictionary to only accept String keys and String values:

HashMap<String, String> stringDictionary = new HashMap<>();
stringDictionary.put("Class", "A template for creating objects.");
stringDictionary.put("Object", "An instance of a class.");

We now have a dictionary that stores pairs of String keys and String values and it has the definition of a Java “Class” and “Object”. The “Class” definition seems a little unhelpful, so let’s update it:

stringDictionary.replace("Class", "A template that defines the attributes and behavior that objects constructed from it can exhibit.");

Instead of calling the put() method again to change the value of the “Class” key in our map, we called the replace() instance method. Calling replace() ensures that the pair will not be added to the map if the key was not already present in the map. If we had called put() instead, the pair would have been added to the map even though we only intended to update the value of the pair. For that reason, you should use replace() to update the value of a pair with a key you know exists in a HashMap and use put() if you want to update the value of a pair with a key you wouldn’t mind adding to your map if it doesn’t already exist. The best of both world, often the better design pattern, would be to check if the key exists in our map before we replace it:

if(stringDictionary.containsKey("Class")) {
stringDictionary.replace("Class", "A better definition.");
} else {
stringDictionary.put("Class", "A descriptive definition");
}

String meaningOfClass = stringDictionary.get("Class");
System.out.println("Class: " + meaningOfClass);
//prints "Class: A better definition."

In that code snippet, we replaced the value of the pair if the key already existed in the map and we added the pair to the map otherwise by checking with containsKey(). If we want to remove a pair from our map, we don’t have to make sure it exists first. We can simply ask the map to remove the pair with a key matching the key we provide as an argument to the remove() method. If the key exists in the map, the corresponding value will be removed return, and otherwise, nothing will be removed and returned:

String valueOfRemovedPair = stringDictionary.remove("Class");
System.out.println("Value of removed 'Class': " + valueOfRemovedPair);
//prints "Value of removed pair with key 'Class': A better definition."

The only thing left to do is clear our dictionary and start over. If we no longer need the pairs in our HashMap, we can remove all of them at once by calling the clear() method:

stringDictionary.clear();
System.out.println("Pairs in our string dictionary: " + stringDictionary.size());
//prints "Pairs in our string dictionary: 0"

Our stringDictionary HashMap is now empty and you are free to add new pairs to it and use it to study up on everything you have learned about Java so far. You could make a study guide by adding each concept to the HashMap along with its meaning, iterate over the map’s keys with Java’s handy iterator method which you can learn about by doing some research on Google, and try to guess the corresponding value of each key before you print it to the console. I’ll get you started in the supporting code.


ModernNerd Code

Learn to Code Life. Subscribe to Video Tutorials on Youtube

Lincoln W Daniel

Written by

My passion is in developing software to enable people to accomplish their goals more efficiently. Author @JavaForHumans.com. Creator of @Smedian.com

ModernNerd Code

Learn to Code Life. Subscribe to Video Tutorials on Youtube

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade