Nugget Friday - Did You Know This About HashMaps?
Originally published on 05 Jul 2024
Last updated on 05 Jul 2024
It’s Friday and we kick off the maiden edition of Nugget Friday. So, what is it? Nugget Friday is going to be a series of short blog posts that focus on hidden nuggets in the various JDK releases since Java 9. In this maiden edition, we look at a very obscure static method on the HashMap class introduced in Java 19.
The Problem
You already know you can initialise a map with a predefined size, right? For example:
Map<String, Rectangle> shapes = new HashMap<>(100);
You probably expect to be able to insert up to 100 elements into the map, right? On the surface, yes. But behind the scenes, the HashMap has a load factor of 0.75 (default value). What is a load factor? Working on the hashing principle, a HashMap dynamically resizes its buckets when its set capacity reaches 75%. This happens independently on whether you explicit set the capacity, like 100 in our example, or not - with the size being 16 by default.
So, for our shapes map, when we insert the 75th element, which is 75% of 100, the HashMap will resize to double the capacity. In this example, this means 200. According to the JavaDoc of HashMap.java, “when the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.”
For large tables, this could get expensive. The JavaDoc further recommends that “if many mappings are to be stored in a HashMap instance, creating it with a sufficiently large capacity will allow the mappings to be stored more efficiently than letting it perform automatic rehashing as needed to grow the table.”
The Solution
For our shapes map, assuming we know ahead of time that we will be storing exactly 100 elements, we can size our initial map to as follows:
Map<String, Rectangle> shapes = new HashMap<>((int) Math.ceil(100 / (double) 0.75));
This should give us an initial capacity of about 133. This way, we get to store our 100 elements in one shot without the map needing to resize. So, instead of ending up with a map with 200 elements of which we use 100, we end up with a map with 133 elements of which we use 100.
Starting with Java 19 however, instead of fiddling with the maths like we did above, you can use the static method:
Map<String, Rectangle> shapes = HashMap.newHashMap(100);
The JavaDoc for this method states that it “creates a new, empty HashMap suitable for the expected number of mappings. The returned map uses the default load factor of 0.75, and its initial capacity is generally large enough so that the expected number of mappings can be added without resizing the map.”
So there you have it! This method creates behind the scene a map that is large enough to accommodate your passed mappings value using the load factor without needing to resize the map. Neat huh? Now, when you need to create a HashMap with a predetermined size, you know which method to use!
That’s it for today. See you next Friday for another nugget. Happy Coding!
Related Posts
Announcing Virtual Payara Conference - Powering High-Performance Enterprise Java Applications
Published on 24 Oct 2024
by Dominika Tasarz
0 Comments
We're super excited to announce the third edition of the Virtual Payara Conference! This December we will be focusing on Powering High-Performance Enterprise Java Applications.
- Strategic Insight - Wednesday 11th December 2024, 1-6:30pm GMT - ...
Join Live Webinar Series - Boost Your System Performance: Troubleshoot Faster & Cut GC Waste
Published on 07 Oct 2024
by Dominika Tasarz
0 Comments
We’re excited to invite you to two informative webinars happening later this month, which we're running in collaboration with yCrash.
During the first webinar, you will learn how to capture 16 essential artifacts that can dramatically ...