<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Collection Framework - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Collection Framework - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 27 Jul 2026 15:22:37 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/collection-framework/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Java Collections Framework – A Guide for Developers ]]>
                </title>
                <description>
                    <![CDATA[ In your Java applications, you’ll typically work with various types of objects. And you might want to perform operations like sorting, searching, and iterating on these objects. Prior to the introduction of the Collections framework in JDK 1.2, you w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/java-collections-framework-reference-guide/</link>
                <guid isPermaLink="false">6798fd38ac05f27ed5691abd</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Collection Framework ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anjan Baradwaj ]]>
                </dc:creator>
                <pubDate>Tue, 28 Jan 2025 15:52:24 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738077724002/cfbf6a90-f9c2-4853-b1c3-c33774f078c1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In your Java applications, you’ll typically work with various types of objects. And you might want to perform operations like sorting, searching, and iterating on these objects.</p>
<p>Prior to the introduction of the Collections framework in JDK 1.2, you would’ve used Arrays and Vectors to store and manage a group of objects. But they had their own share of drawbacks.</p>
<p>The Java Collections Framework aims to overcome these issues by providing high-performance implementations of common data structures. These allow you to focus on writing the application logic instead of focusing on low-level operations.</p>
<p>Then, the introduction of Generics in JDK 1.5 significantly improved the Java Collections Framework. Generics let you enforce type safety for objects stored in a collection, which enhances the robustness of your applications. You can read more about Java Generics <a target="_blank" href="https://www.freecodecamp.org/news/generics-in-java/">here</a>.</p>
<p>In this article, I will guide you through how to use the Java Collections Framework. We’ll discuss the different types of collections, such as Lists, Sets, Queues, and Maps. I’ll also provide a brief explanation of their key characteristics such as:</p>
<ul>
<li><p>Internal mechanisms</p>
</li>
<li><p>Handling of duplicates</p>
</li>
<li><p>Support for null values</p>
</li>
<li><p>Ordering</p>
</li>
<li><p>Synchronization</p>
</li>
<li><p>Performance</p>
</li>
<li><p>Key methods</p>
</li>
<li><p>Common implementations</p>
</li>
</ul>
<p>We’ll also walk through some code examples for better understanding, and I’ll touch on the Collections utility class and its usage.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-understanding-the-java-collections-framework">Understanding the Java Collections Framework</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-collection-interfaces">Collection Interfaces</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-decoding-the-java-collections-framework-hierarchy">Decoding the Java Collections Framework Hierarchy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-closer-look-at-collection-interfaces">A Closer Look at Collection Interfaces</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-java-collection-interfaces">Java Collection Interfaces</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-lists">Lists</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sets">Sets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-queues">Queues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-maps">Maps</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-collections-utility-class">Collections Utility Class</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-understanding-the-java-collections-framework"><strong>Understanding the Java Collections Framework</strong></h2>
<p>According to the Java <a target="_blank" href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html">documentation</a>, “<em>A collection is an object that represents a group of objects. A collections framework is a unified architecture for representing and manipulating collections</em>.”</p>
<p>In simple terms, the Java Collections Framework helps you manage a group of objects and perform operations on them efficiently and in an organized way. It makes it easier to develop applications by offering various methods to handle groups of objects. You can add, remove, search, and sort objects effectively using the Java Collections Framework.</p>
<h3 id="heading-collection-interfaces">Collection Interfaces</h3>
<p>In Java, an interface specifies a contract that must be fulfilled by any class that implements it. This means the implementing class must provide concrete implementations for all the methods declared in the interface.</p>
<p>In the Java Collections Framework, various collection interfaces like <code>Set</code>, <code>List</code>, and <code>Queue</code> extend the <code>Collection</code> interface, and they must adhere to the contract defined by the <code>Collection</code> interface.</p>
<h3 id="heading-decoding-the-java-collections-framework-hierarchy">Decoding the Java Collections Framework Hierarchy</h3>
<p>Check out this neat diagram from this <a target="_blank" href="https://medium.com/@mbanaee61/mastering-the-java-collections-framework-hierarchy-with-java-code-and-junit-testing-ab2eb87746ed">article</a> that illustrates the Java Collection Hierarchy:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736532451482/6ef571c1-afe0-4314-9038-b472b06f4065.webp" alt="Diagram showing the Java Collection Framework hierarchy. It includes interfaces like Iterable, Collection, List, Queue, Set, Map, and SortedMap, with classes such as ArrayList, LinkedList, Vector, Stack, PriorityQueue, Deque, HashSet, LinkedHashSet, SortedSet, TreeSet, Hashtable, LinkedHashMap, HashMap, and TreeMap. Arrows indicate implementation and extension relationships." class="image--center mx-auto" width="822" height="576" loading="lazy"></p>
<p>We’ll start from the top and work down so you can understand what this diagram is showing:</p>
<ol>
<li><p>At the root of the Java Collections Framework is the <code>Iterable</code> interface, which lets you iterate over the elements of a collection.</p>
</li>
<li><p>The <code>Collection</code> interface extends the <code>Iterable</code> interface. This means it inherits the properties and behavior of the <code>Iterable</code> interface and adds its own behavior for adding, removing, and retrieving elements.</p>
</li>
<li><p>Specific interfaces such as <code>List</code>, <code>Set</code>, and <code>Queue</code> further extend the <code>Collection</code> interface. Each of these interfaces has other classes implementing their methods. For example, <code>ArrayList</code> is a popular implementation of the <code>List</code> interface, <code>HashSet</code> implements the <code>Set</code> interface, and so on.</p>
</li>
<li><p>The <code>Map</code> interface is part of the Java Collections Framework, but it does not extend the <code>Collection</code> interface, unlike the others mentioned above.</p>
</li>
<li><p>All the interfaces and classes in this framework are part of the <code>java.util</code> package.</p>
</li>
</ol>
<p>Note: A common source of confusion in the Java Collections Framework revolves around the difference between <code>Collection</code> and <code>Collections</code>. <code>Collection</code> is an interface in the framework, while <code>Collections</code> is a utility class. The <code>Collections</code> class provides static methods that perform operations on the elements of a collection.</p>
<h2 id="heading-java-collection-interfaces">Java Collection Interfaces</h2>
<p>By now, you’re familiar with the different types of collections that form the foundation of the collections framework. Now we’ll take a closer look at the <code>List</code>, <code>Set</code>, <code>Queue</code>, and <code>Map</code> interfaces.</p>
<p>In this section, we'll discuss each of these interfaces while exploring their internal mechanisms. We'll examine how they handle duplicate elements and whether they support the insertion of null values. We'll also understand the ordering of elements during insertion and their support for synchronization, which deals with the concept of thread safety. Then we’ll walk through a few key methods of these interfaces and conclude by reviewing common implementations and their performance for various operations.</p>
<p>Before we begin, let's talk briefly about Synchronization and Performance.</p>
<ul>
<li><p>Synchronization controls access to shared objects by multiple threads, ensuring their integrity and preventing conflicts. This is crucial for maintaining thread safety.</p>
</li>
<li><p>When choosing a collection type, one important factor is its performance during common operations like insertion, deletion, and retrieval. Performance is usually expressed using Big-O notation. You can learn more about it <a target="_blank" href="https://www.freecodecamp.org/news/big-o-notation-why-it-matters-and-why-it-doesnt-1674cfa8a23c/">here</a>.</p>
</li>
</ul>
<h3 id="heading-lists">Lists</h3>
<p>A <code>List</code> is an ordered or sequential collection of elements. It follows zero-based indexing, allowing the elements to be inserted, removed, or accessed using their index position.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>List</code> is internally supported by either an array or a linked list, depending on the type of implementation. For example, an <code>ArrayList</code> uses an array, while a <code>LinkedList</code> uses a linked list internally. You can read more about <code>LinkedList</code> <a target="_blank" href="https://www.freecodecamp.org/news/how-linked-lists-work/">here</a>. A <code>List</code> dynamically resizes itself upon the addition or removal of elements. The indexing-based retrieval makes it a very efficient type of collection.</p>
</li>
<li><p><strong>Duplicates</strong>: Duplicate elements are allowed in a <code>List</code>, which means there can be more than one element in a <code>List</code> with the same value. Any value can be retrieved based on the index at which it is stored.</p>
</li>
<li><p><strong>Null</strong>: Null values are also allowed in a <code>List</code>. Since duplicates are permitted, you can also have multiple null elements.</p>
</li>
<li><p><strong>Ordering</strong>: A <code>List</code> maintains insertion order, meaning the elements are stored in the same order they are added. This is helpful when you want to retrieve elements in the exact order they were inserted.</p>
</li>
<li><p><strong>Synchronization</strong>: A <code>List</code> is not synchronized by default, which means it doesn't have a built-in way to handle access by multiple threads at the same time.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>List</code> interface: <code>add(E element)</code>, <code>get(int index)</code>, <code>set(int index, E element)</code>, <code>remove(int index)</code>, and <code>size()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.ArrayList;
 <span class="hljs-keyword">import</span> java.util.List;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ListExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a list</span>
         List&lt;String&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

         <span class="hljs-comment">// add(E element)</span>
         list.add(<span class="hljs-string">"Apple"</span>);
         list.add(<span class="hljs-string">"Banana"</span>);
         list.add(<span class="hljs-string">"Cherry"</span>);

         <span class="hljs-comment">// get(int index)</span>
         String secondElement = list.get(<span class="hljs-number">1</span>); <span class="hljs-comment">// "Banana"</span>

         <span class="hljs-comment">// set(int index, E element)</span>
         list.set(<span class="hljs-number">1</span>, <span class="hljs-string">"Blueberry"</span>);

         <span class="hljs-comment">// remove(int index)</span>
         list.remove(<span class="hljs-number">0</span>); <span class="hljs-comment">// Removes "Apple"</span>

         <span class="hljs-comment">// size()</span>
         <span class="hljs-keyword">int</span> size = list.size(); <span class="hljs-comment">// 2</span>

         <span class="hljs-comment">// Print the list</span>
         System.out.println(list); <span class="hljs-comment">// Output: [Blueberry, Cherry]</span>

         <span class="hljs-comment">// Print the size of the list</span>
         System.out.println(size); <span class="hljs-comment">// Output: 2</span>
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>ArrayList</code>, <code>LinkedList</code>, <code>Vector</code>, <code>Stack</code></p>
</li>
<li><p><strong>Performance</strong>: Typically, insert and delete operations are fast in both <code>ArrayList</code> and <code>LinkedList</code>. But fetching elements can be slow because you have to traverse through the nodes.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>ArrayList</strong></td><td><strong>LinkedList</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast at the end - O(1) amortized, slow at the beginning or middle- O(n)</td><td>Fast at the beginning or middle - O(1), slow at the end - O(n)</td></tr>
<tr>
<td>Deletion</td><td>Fast at the end - O(1) amortized, slow at the beginning or middle- O(n)</td><td>Fast - O(1) if position is known</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1) for random access</td><td>Slow - O(n) for random access, as it involves traversing</td></tr>
</tbody>
</table>
</div><h3 id="heading-sets">Sets</h3>
<p>A <code>Set</code> is a type of collection that does not allow duplicate elements and represents the concept of a mathematical set.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>Set</code> is internally backed by a <code>HashMap</code>. Depending on the implementation type, it is supported by either a <code>HashMap</code>, <code>LinkedHashMap</code>, or a <code>TreeMap</code>. I have written a detailed article about how <code>HashMap</code> works internally <a target="_blank" href="https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained">here</a>. Be sure to check it out.</p>
</li>
<li><p><strong>Duplicates</strong>: Since a <code>Set</code> represents the concept of a mathematical set, duplicate elements are not allowed. This ensures that all elements are unique, maintaining the integrity of the collection.</p>
</li>
<li><p><strong>Null</strong>: A maximum of one null value is allowed in a <code>Set</code> because duplicates are not permitted. But this does not apply to the <code>TreeSet</code> implementation, where null values are not allowed at all.</p>
</li>
<li><p><strong>Ordering</strong>: Ordering of elements in a <code>Set</code> depends on the type of implementation.</p>
<ul>
<li><p><code>HashSet</code>: Order is not guaranteed, and elements can be placed in any position.</p>
</li>
<li><p><code>LinkedHashSet</code>: This implementation maintains the insertion order, so you can retrieve the elements in the same order they were inserted.</p>
</li>
<li><p><code>TreeSet</code>: Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
</ul>
</li>
<li><p><strong>Synchronization</strong>: A <code>Set</code> is not synchronized, meaning you might encounter concurrency issues, like race conditions, which can affect data integrity if two or more threads try to access a <code>Set</code> object simultaneously</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Set</code> interface: <code>add(E element)</code>, <code>remove(Object o)</code>, <code>contains(Object o)</code>, and <code>size()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.HashSet;
 <span class="hljs-keyword">import</span> java.util.Set;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SetExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a set</span>
         Set&lt;String&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();

         <span class="hljs-comment">// Add elements to the set</span>
         set.add(<span class="hljs-string">"Apple"</span>);
         set.add(<span class="hljs-string">"Banana"</span>);
         set.add(<span class="hljs-string">"Cherry"</span>);

         <span class="hljs-comment">// Remove an element from the set</span>
         set.remove(<span class="hljs-string">"Banana"</span>);

         <span class="hljs-comment">// Check if the set contains an element</span>
         <span class="hljs-keyword">boolean</span> containsApple = set.contains(<span class="hljs-string">"Apple"</span>);
         System.out.println(<span class="hljs-string">"Contains Apple: "</span> + containsApple);

         <span class="hljs-comment">// Get the size of the set</span>
         <span class="hljs-keyword">int</span> size = set.size();
         System.out.println(<span class="hljs-string">"Size of the set: "</span> + size);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>HashSet</code>, <code>LinkedHashSet</code>, <code>TreeSet</code></p>
</li>
<li><p><strong>Performance</strong>: <code>Set</code> implementations offer fast performance for basic operations, except for a <code>TreeSet</code>, where the performance can be relatively slower because the internal data structure involves sorting the elements during these operations.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>HashSet</strong></td><td><strong>LinkedHashSet</strong></td><td><strong>TreeSet</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
</tbody>
</table>
</div><h3 id="heading-queues">Queues</h3>
<p>A <code>Queue</code> is a linear collection of elements used to hold multiple items before processing, usually following the FIFO (first-in-first-out) order. This means elements are added at one end and removed from the other, so the first element added to the queue is the first one removed.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: The internal workings of a <code>Queue</code> can differ based on its specific implementation.</p>
<ul>
<li><p><code>LinkedList</code> – uses a doubly-linked list to store elements, which means you can traverse both forward and backward, allowing for flexible operations.</p>
</li>
<li><p><code>PriorityQueue</code> – is internally backed by a binary heap, which is very efficient for retrieval operations.</p>
</li>
<li><p><code>ArrayDeque</code> – is implemented using an array that expands or shrinks as elements are added or removed. Here, elements can be added or removed from both ends of the queue.</p>
</li>
</ul>
</li>
<li><p><strong>Duplicates</strong>: In a <code>Queue</code>, duplicate elements are permitted, allowing multiple instances of the same value to be inserted</p>
</li>
<li><p><strong>Null</strong>: You cannot insert a null value into a <code>Queue</code> because, by design, some methods of a <code>Queue</code> return null to indicate that it is empty. To avoid confusion, null values are not allowed.</p>
</li>
<li><p><strong>Ordering</strong>: Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
<li><p><strong>Synchronization</strong>: A <code>Queue</code> is not synchronized by default. But, you can use a <code>ConcurrentLinkedQueue</code> or a <code>BlockingQueue</code> implementation for achieving thread safety.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Queue</code> interface: <code>add(E element)</code>, <code>offer(E element)</code>, <code>poll()</code>, and <code>peek()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.LinkedList;
 <span class="hljs-keyword">import</span> java.util.Queue;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QueueExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a queue using LinkedList</span>
         Queue&lt;String&gt; queue = <span class="hljs-keyword">new</span> LinkedList&lt;&gt;();

         <span class="hljs-comment">// Use add method to insert elements, throws exception if insertion fails</span>
         queue.add(<span class="hljs-string">"Element1"</span>);
         queue.add(<span class="hljs-string">"Element2"</span>);
         queue.add(<span class="hljs-string">"Element3"</span>);

         <span class="hljs-comment">// Use offer method to insert elements, returns false if insertion fails</span>
         queue.offer(<span class="hljs-string">"Element4"</span>);

         <span class="hljs-comment">// Display queue</span>
         System.out.println(<span class="hljs-string">"Queue: "</span> + queue);

         <span class="hljs-comment">// Peek at the first element (does not remove it)</span>
         String firstElement = queue.peek();
         System.out.println(<span class="hljs-string">"Peek: "</span> + firstElement); <span class="hljs-comment">// outputs "Element1"</span>

         <span class="hljs-comment">// Poll the first element (retrieves and removes it)</span>
         String polledElement = queue.poll();
         System.out.println(<span class="hljs-string">"Poll: "</span> + polledElement); <span class="hljs-comment">// outputs "Element1"</span>

         <span class="hljs-comment">// Display queue after poll</span>
         System.out.println(<span class="hljs-string">"Queue after poll: "</span> + queue);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>LinkedList</code>, <code>PriorityQueue</code>, <code>ArrayDeque</code></p>
</li>
<li><p><strong>Performance</strong>: Implementations like <code>LinkedList</code> and <code>ArrayDeque</code> are usually quick for adding and removing items. The <code>PriorityQueue</code> is a bit slower because it inserts items based on the set priority order.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>LinkedList</strong></td><td><strong>PriorityQueue</strong></td><td><strong>ArrayDeque</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast at the beginning or middle - O(1), slow at the end - O(n)</td><td>Slower - O(log n)</td><td>Fast - O(1), Slow - O(n), if it involves resizing of the internal array</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1) if position is known</td><td>Slower - O(log n)</td><td>Fast - O(1), Slow - O(n), if it involves resizing of the internal array</td></tr>
<tr>
<td>Retrieval</td><td>Slow - O(n) for random access, as it involves traversing</td><td>Fast - O(1)</td><td>Fast - O(1)</td></tr>
</tbody>
</table>
</div><h3 id="heading-maps">Maps</h3>
<p>A <code>Map</code> represents a collection of key-value pairs, with each key mapping to a single value. Although <code>Map</code> is part of the Java Collection framework, it does not extend the <code>java.util.Collection</code> interface.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>Map</code> works internally using a <code>HashTable</code> based on the concept of hashing. I have written a detailed <a target="_blank" href="https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained">article</a> on this topic, so give it a read for a deeper understanding.</p>
</li>
<li><p><strong>Duplicates</strong>: A <code>Map</code> stores data as key-value pairs. Here, each key is unique, so duplicate keys are not allowed. But duplicate values are permitted.</p>
</li>
<li><p><strong>Null</strong>: Since duplicate keys are not allowed, a <code>Map</code> can have only one null key. As duplicate values are permitted, it can have multiple null values. In the <code>TreeMap</code> implementation, keys cannot be null because it sorts the elements based on the keys. However, null values are allowed.</p>
</li>
<li><p><strong>Ordering</strong>: Insertion order of a <code>Map</code> varies on the implementation:</p>
<ul>
<li><p><code>HashMap</code> – the insertion order is not guaranteed as they are determined based on the concept of hashing.</p>
</li>
<li><p><code>LinkedHashMap</code> – the insertion order is preserved and you can retrieve the elements back in the same order that they were added into the collection.</p>
</li>
<li><p><code>TreeMap</code> – Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
</ul>
</li>
<li><p><strong>Synchronization</strong>: A <code>Map</code> is not synchronized by default. But you can use <code>Collections.synchronizedMap()</code> or <code>ConcurrentHashMap</code> implementations for achieving thread safety.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Map</code> interface: <code>put(K key, V value)</code>, <code>get(Object key)</code>, <code>remove(Object key)</code>, <code>containsKey(Object key)</code>, and <code>keySet()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.HashMap;
 <span class="hljs-keyword">import</span> java.util.Map;
 <span class="hljs-keyword">import</span> java.util.Set;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MapMethodsExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a new HashMap</span>
         Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

         <span class="hljs-comment">// put(K key, V value) - Inserts key-value pairs into the map</span>
         map.put(<span class="hljs-string">"Apple"</span>, <span class="hljs-number">1</span>);
         map.put(<span class="hljs-string">"Banana"</span>, <span class="hljs-number">2</span>);
         map.put(<span class="hljs-string">"Orange"</span>, <span class="hljs-number">3</span>);

         <span class="hljs-comment">// get(Object key) - Returns the value associated with the key</span>
         Integer value = map.get(<span class="hljs-string">"Banana"</span>);
         System.out.println(<span class="hljs-string">"Value for 'Banana': "</span> + value);

         <span class="hljs-comment">// remove(Object key) - Removes the key-value pair for the specified key</span>
         map.remove(<span class="hljs-string">"Orange"</span>);

         <span class="hljs-comment">// containsKey(Object key) - Checks if the map contains the specified key</span>
         <span class="hljs-keyword">boolean</span> hasApple = map.containsKey(<span class="hljs-string">"Apple"</span>);
         System.out.println(<span class="hljs-string">"Contains 'Apple': "</span> + hasApple);

         <span class="hljs-comment">// keySet() - Returns a set view of the keys contained in the map</span>
         Set&lt;String&gt; keys = map.keySet();
         System.out.println(<span class="hljs-string">"Keys in map: "</span> + keys);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>HashMap</code>, <code>LinkedHashMap</code>, <code>TreeMap</code>, <code>Hashtable</code>, <code>ConcurrentHashMap</code></p>
</li>
<li><p><strong>Performance</strong>: <code>HashMap</code> implementation is widely used mainly due to its efficient performance characteristics depicted in the below table.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>HashMap</strong></td><td><strong>LinkedHashMap</strong></td><td><strong>TreeMap</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
</tbody>
</table>
</div><h2 id="heading-collections-utility-class">Collections Utility Class</h2>
<p>As highlighted at the beginning of this article, the <code>Collections</code> utility class has several useful static methods that let you perform commonly used operations on the elements of a collection. These methods help you reduce the boilerplate code in your application and lets you focus on the business logic.</p>
<p>Here are some key features and methods, along with what they do, listed briefly:</p>
<ol>
<li><p><strong>Sorting:</strong> <code>Collections.sort(List&lt;T&gt;)</code> – this method is used to sort the elements of a list in ascending order.</p>
</li>
<li><p><strong>Searching:</strong> <code>Collections.binarySearch(List&lt;T&gt;, key)</code> – this method is used to search for a specific element in a sorted list and return its index.</p>
</li>
<li><p><strong>Reverse order:</strong> <code>Collections.reverse(List&lt;T&gt;)</code> – this method is used to reverse the order of elements in a list.</p>
</li>
<li><p><strong>Min/Max Operations:</strong> <code>Collections.min(Collection&lt;T&gt;)</code> and <code>Collections.max(Collection&lt;T&gt;)</code> – these methods are used to find the minimum and maximum elements in a collection, respectively.</p>
</li>
<li><p><strong>Synchronization:</strong> <code>Collections.synchronizedList(List&lt;T&gt;)</code> – this method is used to make a list thread-safe by synchronizing it.</p>
</li>
<li><p><strong>Unmodifiable Collections:</strong> <code>Collections.unmodifiableList(List&lt;T&gt;)</code> – this method is used to create a read-only view of a list, preventing modifications.</p>
</li>
</ol>
<p>Here's a sample Java program that demonstrates various functionalities of the <code>Collections</code> utility class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollectionsExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Integer&gt; numbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        numbers.add(<span class="hljs-number">5</span>);
        numbers.add(<span class="hljs-number">3</span>);
        numbers.add(<span class="hljs-number">8</span>);
        numbers.add(<span class="hljs-number">1</span>);

        <span class="hljs-comment">// Sorting</span>
        Collections.sort(numbers);
        System.out.println(<span class="hljs-string">"Sorted List: "</span> + numbers);

        <span class="hljs-comment">// Searching</span>
        <span class="hljs-keyword">int</span> index = Collections.binarySearch(numbers, <span class="hljs-number">3</span>);
        System.out.println(<span class="hljs-string">"Index of 3: "</span> + index);

        <span class="hljs-comment">// Reverse Order</span>
        Collections.reverse(numbers);
        System.out.println(<span class="hljs-string">"Reversed List: "</span> + numbers);

        <span class="hljs-comment">// Min/Max Operations</span>
        <span class="hljs-keyword">int</span> min = Collections.min(numbers);
        <span class="hljs-keyword">int</span> max = Collections.max(numbers);
        System.out.println(<span class="hljs-string">"Min: "</span> + min + <span class="hljs-string">", Max: "</span> + max);

        <span class="hljs-comment">// Synchronization</span>
        List&lt;Integer&gt; synchronizedList = Collections.synchronizedList(numbers);
        System.out.println(<span class="hljs-string">"Synchronized List: "</span> + synchronizedList);

        <span class="hljs-comment">// Unmodifiable Collections</span>
        List&lt;Integer&gt; unmodifiableList = Collections.unmodifiableList(numbers);
        System.out.println(<span class="hljs-string">"Unmodifiable List: "</span> + unmodifiableList);
    }
}
</code></pre>
<p>This program demonstrates sorting, searching, reversing, finding minimum and maximum values, synchronizing, and creating an unmodifiable list using the <code>Collections</code> utility class.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you’ve learned about the Java Collections Framework and how it helps manage groups of objects in Java applications. We explored various collection types like Lists, Sets, Queues, and Maps and gained insight into some of the key characteristics and how each of these types supports them.</p>
<p>You learned about performance, synchronization, and key methods, gaining valuable insights into choosing the right data structures for your needs.</p>
<p>By understanding these concepts, you can fully utilize the Java Collections Framework, allowing you to write more efficient code and build robust applications.</p>
<p>If you found this article interesting, feel free to check out my other articles on <a target="_blank" href="https://www.freecodecamp.org/news/author/anjanbaradwaj/">freeCodeCamp</a> and connect with me on <a target="_blank" href="https://www.linkedin.com/in/abaradwaj/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Java HashMaps Work – Internal Mechanics Explained ]]>
                </title>
                <description>
                    <![CDATA[ A HashMap is one of the most commonly used data structures in Java, and it's known for its efficiency. Data in a HashMap is stored in the form of key-value pairs. In this article, I will introduce you to HashMaps in Java. We will explore the common o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained/</link>
                <guid isPermaLink="false">66b677afa502c749ffbb5c36</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hashmap ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Collection Framework ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anjan Baradwaj ]]>
                </dc:creator>
                <pubDate>Fri, 09 Aug 2024 20:10:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Or_Fa550XaQ/upload/f4d40f1c8e94855d53776a3bb6179673.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A <code>HashMap</code> is one of the most commonly used data structures in Java, and it's known for its efficiency. Data in a <code>HashMap</code> is stored in the form of key-value pairs.</p>
<p>In this article, I will introduce you to <code>HashMap</code>s in Java. We will explore the common operations of <code>HashMap</code> and then delve into how it operates internally. You will gain an understanding of the hash function and how index calculation takes place. Finally, we will look at the time complexities of the operations and touch upon the behavior in a concurrent environment.</p>
<h2 id="heading-what-is-a-hashmap-in-java"><strong>What is a</strong> <code>HashMap</code> in Java?</h2>
<p>A <code>HashMap</code> implements the <code>Map</code> interface, which is part of the Java collection framework. It's based on the concept of Hashing.</p>
<p>Hashing is a technique that transforms an input of arbitrary size into a fixed-size output using a hash function. The generated output is called the hash code and is represented by an integer value in Java. Hash codes are used for efficient lookup and storage operations in a <code>HashMap</code>.</p>
<h2 id="heading-common-operations"><strong>Common Operations</strong></h2>
<p>Like we discussed above, data in a <code>HashMap</code> is stored in the form of key-value pairs. The key is a unique identifier, and each key is associated with a value.</p>
<p>Below are some common operations supported by a <code>HashMap</code>. Let's understand what these methods do with some simple code examples:</p>
<h3 id="heading-insertion"><strong>Insertion</strong></h3>
<ul>
<li><p>This method inserts a new key-value pair to the <code>HashMap</code>.</p>
</li>
<li><p>The insertion order of the key-value pairs is not maintained.</p>
</li>
<li><p>During insertion, if a key is already present, the existing value will be replaced with the new value that is passed.</p>
</li>
<li><p>You can insert only one null key into the <code>HashMap</code>, but you can have multiple null values.</p>
</li>
</ul>
<p>The method signature for this operation is given below, followed by an example:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> V <span class="hljs-title">put</span><span class="hljs-params">(K key, V value)</span></span>
</code></pre>
<pre><code class="lang-java">Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
map.put(<span class="hljs-string">"apple"</span>, <span class="hljs-number">1</span>);
map.put(<span class="hljs-string">"banana"</span>, <span class="hljs-number">2</span>);
</code></pre>
<p>In the code above, we have a HashMap example where we add a key of type String and value of type Integer.</p>
<h3 id="heading-retrieval"><strong>Retrieval:</strong></h3>
<ul>
<li><p>Fetches the value associated with a given key.</p>
</li>
<li><p>Returns <code>null</code> if the key does not exist in the <code>HashMap</code>.</p>
</li>
</ul>
<p>The method signature for this operation is given below, followed by an example:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> V <span class="hljs-title">get</span><span class="hljs-params">(Object key)</span></span>
</code></pre>
<pre><code class="lang-java">Integer value = map.get(<span class="hljs-string">"apple"</span>); <span class="hljs-comment">// returns 1</span>
</code></pre>
<p>In the code above, we're retrieving the value associated with the key <code>apple</code>.</p>
<p>Other common operations include:</p>
<ul>
<li><p><code>remove</code>: Removes the key-value pair for the specified key. It returns <code>null</code> if the key is not found.</p>
</li>
<li><p><code>containsKey</code>: Checks if a specific key is present in the <code>HashMap</code>.</p>
</li>
<li><p><code>containsValue</code>: Checks if the specified value is present in the <code>HashMap</code>.</p>
</li>
</ul>
<h2 id="heading-internal-structure-of-a-hashmap"><strong>Internal Structure of a</strong> <code>HashMap</code></h2>
<p>Internally, a <code>HashMap</code> uses an array of buckets or bins. Each bucket is a linked list of type <code>Node</code>, which is used to represent the key-value pair of the <code>HashMap</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>&lt;<span class="hljs-title">K</span>, <span class="hljs-title">V</span>&gt; </span>{
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> hash;
    <span class="hljs-keyword">final</span> K key;
    V value;
    Node&lt;K, V&gt; next;

    Node(<span class="hljs-keyword">int</span> hash, K key, V value, Node&lt;K, V&gt; next) {
        <span class="hljs-keyword">this</span>.hash = hash;
        <span class="hljs-keyword">this</span>.key = key;
        <span class="hljs-keyword">this</span>.value = value;
        <span class="hljs-keyword">this</span>.next = next;
    }
}
</code></pre>
<p>Above, you can see the structure of the <code>Node</code> class which is used to store the key-value pairs of the <code>HashMap</code>.</p>
<p>The <code>Node</code> class has the following fields:</p>
<ul>
<li><p><code>hash</code>: Refers to the <code>hashCode</code> of the key.</p>
</li>
<li><p><code>key</code>: Refers to the key of the key-value pair.</p>
</li>
<li><p><code>value</code>: Refers to the value associated with the key.</p>
</li>
<li><p><code>next</code>: Acts as a reference to the next node.</p>
</li>
</ul>
<p>The <code>HashMap</code> is fundamentally based on a hash table implementation, and its performance depends on two key parameters: initial capacity and load factor. The <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/Hashtable.html">original javadocs</a> of the Hash table class define these two parameters as follows:</p>
<ul>
<li><p>The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created.</p>
</li>
<li><p>The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.</p>
</li>
</ul>
<p>Let's now try and understand how the basic operations, <code>put</code> and <code>get</code>, work in a <code>HashMap</code>.</p>
<h3 id="heading-hash-function"><strong>Hash Function</strong></h3>
<p>During the insertion (<code>put</code>) of a key-value pair, the <code>HashMap</code> first calculates the hash code of the key. The hash function then computes an integer for the key. Classes can use the <code>hashCode</code> method of the <code>Object</code> class or override this method and provide their own implementation. (Read about the hash code contract <a target="_blank" href="https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()">here</a>). The hash code is then XORed (eXclusive OR) with its upper 16 bits (h &gt;&gt;&gt; 16) to achieve a more uniform distribution.</p>
<p>XOR is a bitwise operation that compares two bits, resulting in 1 if the bits are different and 0 if they are the same. In this context, performing a bitwise XOR operation between the hash code and its upper 16 bits (obtained using the unsigned right shift <code>&gt;&gt;&gt;</code> operator) helps to mix the bits, leading to a more evenly distributed hash code.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hash</span><span class="hljs-params">(Object key)</span> </span>{
    <span class="hljs-keyword">int</span> h;
    <span class="hljs-keyword">return</span> (key == <span class="hljs-keyword">null</span>) ? <span class="hljs-number">0</span> : (h = key.hashCode()) ^ (h &gt;&gt;&gt; <span class="hljs-number">16</span>);
}
</code></pre>
<p>Above, you can see the static hash method of the <code>HashMap</code> class.</p>
<p>The idea is to have a unique hash code for each key, but the hash function could produce the same hash code for different keys. This leads to a situation known as a collision. We will see how to handle collisions in the next section.</p>
<h3 id="heading-index-calculation"><strong>Index Calculation</strong></h3>
<p>Once the hash code for a key is generated, the <code>HashMap</code> calculates an index within the array of buckets to determine where the key-value pair will be stored. This is done using a bitwise AND operation, which is an efficient way to calculate the modulo when the array length is a power of two.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> index = (n - <span class="hljs-number">1</span>) &amp; hash;
</code></pre>
<p>Here, we're calculating the index where n is the length of the bucket array.</p>
<p>Once the index is calculated, the key is then stored at that index in the bucket array. However, if multiple keys end up having the same index, it causes a collision. In such a scenario, the <code>HashMap</code> handles it in one of two ways:</p>
<ul>
<li><p>Chaining/Linking: Each bucket in the array is a linked list of nodes. If a key already exists at a particular index and another key gets hashed to the same index, it gets appended to the list.</p>
</li>
<li><p>Treeify: If the number of nodes exceeds a certain threshold, the linked list is converted into a tree (This was introduced in Java 8).</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> TREEIFY_THRESHOLD = <span class="hljs-number">8</span>;
</code></pre>
<p>This is the threshold that determines treeification.</p>
<p>Therefore, it is essential to have a good hash function that uniformly distributes the keys across the buckets and minimizes the chances of collisions.</p>
<p>The retrieval (<code>get</code>) and deletion (<code>remove</code>) operations work similarly to the insertion (<code>put</code>) operation. Here's how:</p>
<ul>
<li><p>Retrieval (<code>get</code>): Computes the hash code using the hash function -&gt; calculates the index using the hash code -&gt; traverses the linked list or tree to find the node with the matching key.</p>
</li>
<li><p>Deletion (<code>remove</code>): Computes the hash code using the hash function -&gt; calculates the index using the hash code -&gt; removes the node from the linked list or tree.</p>
</li>
</ul>
<h3 id="heading-time-complexity"><strong>Time Complexity</strong></h3>
<p>The basic operations of a <code>HashMap</code>, such as <code>put</code>, <code>get</code>, and <code>remove</code>, generally offer constant time performance of O(1), assuming that the keys are uniformly distributed. In cases where there is poor key distribution and many collisions occur, these operations might degrade to a linear time complexity of O(n).</p>
<p>Under treeification, where long chains of collisions are converted into balanced trees, lookup operations can improve to a more efficient logarithmic time complexity of O(log n).</p>
<h3 id="heading-synchronization"><strong>Synchronization</strong></h3>
<p>The <code>HashMap</code> implementation is not synchronized. If multiple threads access a HashMap instance concurrently and iterate over the map, and if any one of the threads performs a structural modification (such as adding or removing a key-value mapping) on the map, it leads to a <code>ConcurrentModificationException</code>.</p>
<p>To prevent this, you can create a thread-safe instance using the <code>Collections.synchronizedMap</code> method.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In summary, understanding the internal workings of a <code>HashMap</code> is crucial for developers to make informed decisions. Knowing how a key is mapped, how collisions happen, and how they can be avoided helps you use the <code>HashMap</code> efficiently and effectively.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
