<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gurpreet</title>
    <description>The latest articles on DEV Community by Gurpreet (@gurpreet_d921f9fff6fa7442).</description>
    <link>https://dev.to/gurpreet_d921f9fff6fa7442</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3575767%2F1fad143b-cfcf-4d68-8ae9-837fc48d201b.png</url>
      <title>DEV Community: Gurpreet</title>
      <link>https://dev.to/gurpreet_d921f9fff6fa7442</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gurpreet_d921f9fff6fa7442"/>
    <language>en</language>
    <item>
      <title>Longest Substring Without Repeating Characters</title>
      <dc:creator>Gurpreet</dc:creator>
      <pubDate>Fri, 24 Oct 2025 17:03:53 +0000</pubDate>
      <link>https://dev.to/gurpreet_d921f9fff6fa7442/longest-substring-without-repeating-characters-306o</link>
      <guid>https://dev.to/gurpreet_d921f9fff6fa7442/longest-substring-without-repeating-characters-306o</guid>
      <description>&lt;p&gt;Given a string s, find the length of the longest substring without duplicate characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;example 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Input: s = "abcabcbb" Output: 3 &lt;/p&gt;

&lt;p&gt;Explanation: The answer is "abc", with the length of 3. Note that "bca" and "cab" are also correct answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brute Force Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Initialize a variable maxLength to 0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a nested loop to generate every possible substring. The outer loop, with index i, defines the start of the substring. The inner loop, with index j, defines the end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each substring, use a third loop or a hash set to check if it contains repeating characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an empty set to store characters for the current substring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iterate through the substring from i to j.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each character, check if it is already in the set. If it is, the substring has duplicates, so you can stop checking this substring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the character is not in the set, add it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the substring is found to have all unique characters, calculate its length (j - i + 1) and update maxLength if the new length is greater.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After checking all possible substrings, the final maxLength will be the answer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity: O(N³)&lt;/strong&gt; The outer two loops that generate all substrings contribute &lt;strong&gt;O(N²)&lt;/strong&gt;.The inner check for unique characters in each substring takes an additional &lt;strong&gt;O(N)&lt;/strong&gt; time in the worst case, leading to a total time complexity of &lt;strong&gt;O(N³)&lt;/strong&gt;. This can be optimized to &lt;strong&gt;O(N²)&lt;/strong&gt; if the uniqueness check is done more efficiently by using a set that is cleared for each new substring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(M)&lt;/strong&gt;. The space complexity is determined by the storage needed to check for unique characters in each substring. In the worst-case scenario, the substring could be the entire string, so a hash set would require space proportional to the number of unique characters, M, which is at most N.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimal Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sliding window technique with HashSet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Initialize two pointers start and end at the beginning of the string and a HashSet set to store unique characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iterate over the String using end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the character at end is not in hashset, insert character in hashset, calculate the current window size end-start+1 and increment end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if the character is present in the hashset, shrink window from the left until the duplicate character is removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;continue till end reaches end of the string.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution {
    public int lengthOfLongestSubstring(String s) {
        int len=0,start=0,end=0,n=s.length();
        HashSet set = new HashSet&amp;lt;&amp;gt;();

        while(end&amp;lt;n){
         while(set.contains(s.charAt(end))&amp;amp;&amp;amp; start&amp;lt;end){

            set.remove(s.charAt(start));
            start++;
         }
         set.add(s.charAt(end));
         len=Math.max(len,end-start+1);
         end++;
        }
        return len;



    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Time Complexity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The time complexity of the sliding window approach using a hash set is &lt;strong&gt;O(N)&lt;/strong&gt;, where n is the length of the string.&lt;/p&gt;

&lt;p&gt;The end pointer iterates through the string from start to end, processing each character once.&lt;/p&gt;

&lt;p&gt;The start pointer also moves through the string, but it only advances forward. In the worst case, it will traverse the length of the string once.&lt;/p&gt;

&lt;p&gt;The hash set operations—add, remove, and contains—have an average-case time complexity of &lt;strong&gt;O(1)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since both pointers traverse the string linearly and the hash set operations are constant time, the overall time complexity is linear, or &lt;strong&gt;O(N)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Space Complexity&lt;/p&gt;

&lt;p&gt;The space complexity is &lt;strong&gt;O(k)&lt;/strong&gt; or &lt;strong&gt;O(min(N,k))&lt;/strong&gt;, where k is the size of the character set (or alphabet).&lt;/p&gt;

&lt;p&gt;The hash set stores unique characters within the current sliding window.&lt;/p&gt;

&lt;p&gt;In the worst-case scenario, all characters in the string are unique, and the size of the hash set will be equal to the length of the string (N).&lt;/p&gt;

&lt;p&gt;However, the size of the hash set is also bounded by the size of the character set. For example, with standard ASCII characters, the set can hold at most 128 elements.&lt;/p&gt;

&lt;p&gt;Therefore, the space required is the minimum of the string length and the size of the character set. For a fixed, small character set like ASCII, the space complexity can be considered O(1)(constant).&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>interview</category>
      <category>leetcode</category>
    </item>
    <item>
      <title>The Magic Behind Instant Lookups: Understanding Hashing and Java's HashMap</title>
      <dc:creator>Gurpreet</dc:creator>
      <pubDate>Wed, 22 Oct 2025 17:29:50 +0000</pubDate>
      <link>https://dev.to/gurpreet_d921f9fff6fa7442/the-magic-behind-instant-lookups-understanding-hashing-and-javas-hashmap-16ab</link>
      <guid>https://dev.to/gurpreet_d921f9fff6fa7442/the-magic-behind-instant-lookups-understanding-hashing-and-javas-hashmap-16ab</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. Hashing: The Core Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hashing is a technique used to convert a large key into a small integer value that serves as an index in an array. This array is called a &lt;strong&gt;Hash Table&lt;/strong&gt;. The primary goal is to achieve near-O(1) (constant time) complexity for insertion, deletion, and retrieval operations.&lt;/p&gt;

&lt;p&gt;What is a Hash Function?&lt;br&gt;
The &lt;strong&gt;Hash Function&lt;/strong&gt; is the mathematical algorithm that performs the conversion. A good hash function is crucial for efficiency and should possess the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic:&lt;/strong&gt; The same key must always produce the same hash code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uniform Distribution:&lt;/strong&gt; It should distribute keys as evenly as possible across the entire range of hash table indices to minimize collisions.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fast Computation:&lt;/strong&gt; It must be quick to calculate.&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   index = HashFunction(Key) (mod TableSize) 
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a visual representation of how a hash function maps keys to indices in a hash table:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F831vsk8d4fud1772ox7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F831vsk8d4fud1772ox7x.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Challenge: Collisions&lt;/strong&gt;&lt;br&gt;
A &lt;strong&gt;collision&lt;/strong&gt; occurs when two different keys hash to the same index in the hash table. Since the index space is smaller than the key space, collisions are unavoidable. Handling them efficiently is the central challenge in &lt;strong&gt;hashing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Hashing Techniques:&lt;/strong&gt; &lt;strong&gt;Collision Resolution&lt;/strong&gt;&lt;br&gt;
There are two primary strategies for resolving collisions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1. Separate Chaining (Open Hashing)&lt;/strong&gt;&lt;br&gt;
In this technique, each bucket (index) in the hash table array holds a pointer to a &lt;strong&gt;linked list&lt;/strong&gt; (or a similar dynamic structure, like a balanced binary search tree in modern Java).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How it Works:&lt;/strong&gt; When a collision occurs, the new key-value pair is simply added to the linked list at that index.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Simple to implement, never runs out of space, and performance degrades gracefully as the load factor increases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Requires extra space for pointers, and traversing the linked list can degrade performance to O(N) in the worst case (where N is the number of elements).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8b6cyef56f9gfaptzqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8b6cyef56f9gfaptzqc.png" alt="Separate Chaining"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.2. Open Addressing (Closed Hashing)&lt;/strong&gt;&lt;br&gt;
In open addressing, all elements are stored directly within the hash table array itself. When a collision occurs, the algorithm &lt;strong&gt;probes&lt;/strong&gt;(searches) for the next available empty slot.&lt;br&gt;
Common probing techniques include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Linear Probing:&lt;/strong&gt; Searches the next slot sequentially: &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          index = (hash + i) (mod TableSize)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Quadratic Probing:&lt;/strong&gt; Searches slots at quadratic intervals:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;           index = (hash + i^2) (mod TableSize)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Double Hashing:&lt;/strong&gt; Uses a second hash function to determine the step size for probing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Better cache performance (elements are stored contiguously), no need for external data structures (like linked lists).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Prone to &lt;strong&gt;clustering&lt;/strong&gt; (groups of filled slots), requires careful load factor management, and deletion can be complex.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Hash Table and Hash Map: Clarified&lt;/strong&gt;&lt;br&gt;
A &lt;strong&gt;Hash Table&lt;/strong&gt; is the generic data structure that implements the principle of hashing to store key-value pairs.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Hash Map&lt;/strong&gt; is an implementation of the Hash Table concept, typically referring to the specific class implementation in various programming languages (e.g., HashMap in Java).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Factor and Rehashing&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Load Factor&lt;/strong&gt; (α) is a critical metric:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;α=Number of EntriesTable Size
\text{α} = \frac{\text{Number of Entries}}{\text{Table Size}}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Table Size&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Number of Entries&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;​If the load factor gets too high (typically &amp;gt;0.75), collisions become frequent, and performance degrades. To maintain near O(1) performance, the Hash Table undergoes &lt;strong&gt;Rehashing&lt;/strong&gt; (or resizing). This involves:&lt;/p&gt;

&lt;p&gt;Creating a new, larger internal array (e.g., double the current size).&lt;/p&gt;

&lt;p&gt;Iterating through all existing entries.&lt;/p&gt;

&lt;p&gt;Re-calculating their hash codes and inserting them into the new, larger array. This process is an O(N) operation, which is why it's done infrequently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Hashing in Java:&lt;/strong&gt; hashCode() &lt;strong&gt;and&lt;/strong&gt; equals()&lt;br&gt;
Java's collection framework heavily relies on hashing, primarily through the java.util.Map interface and its implementing classes like HashMap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Java Hashing Contract&lt;/strong&gt;&lt;br&gt;
For any custom object to be used effectively as a key in a HashMap, it must correctly implement the hashCode() and equals() methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If two objects are equal according to the&lt;/strong&gt; equals(Object) &lt;strong&gt;method, then calling the&lt;/strong&gt; hashCode() &lt;strong&gt;method on each of the two objects must produce the same integer result.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If the&lt;/strong&gt; hashCode() &lt;strong&gt;method produces the same integer result for two objects, they are NOT necessarily equal&lt;/strong&gt; (this indicates a collision).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: If you override equals() without overriding hashCode(), a key inserted might hash to index 'X', but when you try to retrieve it later, the default hashCode() (which doesn't consider the new equals() logic) might hash it to a different index 'Y', making the object "un-findable."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Detail: Java 8+ Enhancement&lt;/strong&gt;&lt;br&gt;
In Java 8 and later, the internal structure of HashMap was improved. A single bucket that contains a very long linked list (due to numerous collisions, which degrades lookup to O(N)) is dynamically converted into a **Balanced Binary Search Tree (specifically a Red-Black Tree) **when the number of elements in the chain exceeds a certain threshold (usually 8). This upgrade improves the worst-case time complexity of lookup, insertion, and deletion from O(N) to O(logN).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Java's Map Implementations: HashMap vs. Hashtable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While both classes implement the Map interface and use the hashing principle, they have key differences that dictate their use cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;HashMap (Recommended for modern code)&lt;/th&gt;
&lt;th&gt;Hashtable (Legacy Class)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Synchronization&lt;/td&gt;
&lt;td&gt;Non-synchronized (Not thread-safe)&lt;/td&gt;
&lt;td&gt;Synchronized (Thread-safe)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Faster (No overhead of synchronization)&lt;/td&gt;
&lt;td&gt;Slower (Synchronization overhead)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nulls&lt;/td&gt;
&lt;td&gt;Allows one null key and multiple null values&lt;/td&gt;
&lt;td&gt;Does not allow null keys or null values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration&lt;/td&gt;
&lt;td&gt;Uses Iterator (Fail-Fast)&lt;/td&gt;
&lt;td&gt;Uses Enumerator and Iterator (Enumerator is not Fail-Fast)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inheritance&lt;/td&gt;
&lt;td&gt;Extends AbstractMap&lt;/td&gt;
&lt;td&gt;Extends Dictionary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary Use&lt;/td&gt;
&lt;td&gt;Single-threaded environments, high-performance needs&lt;/td&gt;
&lt;td&gt;Legacy code or when a simple, fully synchronized map is absolutely required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Code Example: HashMap in Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's a basic Java code snippet demonstrating the use of HashMap:&lt;/p&gt;

&lt;p&gt;Java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        // Declaring a HashMap
        Map&amp;lt;String, Integer&amp;gt; studentScores = new HashMap&amp;lt;&amp;gt;();

        // Adding key-value pairs
        studentScores.put("Alice", 95);
        studentScores.put("Bob", 88);
        studentScores.put("Charlie", 92);
        studentScores.put("David", 88); // David also has a score of 88

        System.out.println("Student Scores: " + studentScores);
        // Output: Student Scores: {Alice=95, Charlie=92, Bob=88, David=88} (Order not guaranteed)

        // Getting a value
        int bobScore = studentScores.get("Bob");
        System.out.println("Bob's score: " + bobScore); // Output: Bob's score: 88

        // Updating a value
        studentScores.put("Alice", 97);
        System.out.println("Alice's new score: " + studentScores.get("Alice")); // Output: Alice's new score: 97

        // Checking if a key exists
        boolean hasCharlie = studentScores.containsKey("Charlie");
        System.out.println("Does Charlie exist? " + hasCharlie); // Output: Does Charlie exist? true

        // Checking if a value exists
        boolean hasScore90 = studentScores.containsValue(90);
        System.out.println("Is there a student with score 90? " + hasScore90); // Output: Is there a student with score 90? false

        // Removing a key-value pair
        studentScores.remove("David");
        System.out.println("Student Scores after removing David: " + studentScores);
        // Output: Student Scores after removing David: {Alice=97, Charlie=92, Bob=88}

        // Iterating through the HashMap
        System.out.println("\nIterating through student scores:");
        for (Map.Entry&amp;lt;String, Integer&amp;gt; entry : studentScores.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        /*
        Output:
        Alice: 97
        Charlie: 92
        Bob: 88
        */
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Example: Hashtable in Action&lt;/strong&gt;&lt;br&gt;
And here's how you'd use a Hashtable. Notice the similar API but with the restrictions mentioned (no nulls) and its synchronized nature.&lt;/p&gt;

&lt;p&gt;Java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.Hashtable;
import java.util.Map;
import java.util.Enumeration; // For legacy iteration

public class HashtableExample {
    public static void main(String[] args) {
        // Declaring a Hashtable
        Hashtable&amp;lt;String, String&amp;gt; capitalCities = new Hashtable&amp;lt;&amp;gt;();

        // Adding key-value pairs
        capitalCities.put("USA", "Washington D.C.");
        capitalCities.put("France", "Paris");
        capitalCities.put("Japan", "Tokyo");
        capitalCities.put("Germany", "Berlin");

        System.out.println("Capital Cities: " + capitalCities);
        // Output: Capital Cities: {Japan=Tokyo, USA=Washington D.C., Germany=Berlin, France=Paris} (Order not guaranteed)

        // Getting a value
        String usaCapital = capitalCities.get("USA");
        System.out.println("Capital of USA: " + usaCapital); // Output: Capital of USA: Washington D.C.

        // Attempting to add a null key (will throw NullPointerException)
        try {
            // capitalCities.put(null, "Invalid");
        } catch (NullPointerException e) {
            System.out.println("Cannot add null key to Hashtable: " + e.getMessage());
        }

        // Attempting to add a null value (will throw NullPointerException)
        try {
            // capitalCities.put("Spain", null);
        } catch (NullPointerException e) {
            System.out.println("Cannot add null value to Hashtable: " + e.getMessage());
        }

        // Iterating through the Hashtable using Enumeration (legacy way)
        System.out.println("\nIterating through capital cities (using Enumeration):");
        Enumeration&amp;lt;String&amp;gt; keys = capitalCities.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            System.out.println(key + ": " + capitalCities.get(key));
        }
        /*
        Output:
        Japan: Tokyo
        USA: Washington D.C.
        Germany: Berlin
        France: Paris
        */

        // Iterating through the Hashtable using Map.Entry (modern way, also works)
        System.out.println("\nIterating through capital cities (using Map.Entry):");
        for (Map.Entry&amp;lt;String, String&amp;gt; entry : capitalCities.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Thread-Safe Alternative&lt;br&gt;
For thread-safe operations in modern Java, the preferred choice is usually ConcurrentHashMap, which offers much higher performance and better concurrency than the legacy Hashtable by using a more granular locking mechanism.&lt;/p&gt;

</description>
      <category>hashing</category>
      <category>hashtable</category>
      <category>hashmap</category>
      <category>dsa</category>
    </item>
    <item>
      <title>Why I’m Starting My Debt-Free Journey (While Learning to Code)</title>
      <dc:creator>Gurpreet</dc:creator>
      <pubDate>Mon, 20 Oct 2025 15:30:54 +0000</pubDate>
      <link>https://dev.to/gurpreet_d921f9fff6fa7442/why-im-starting-my-debt-free-journey-while-learning-to-code-2g6p</link>
      <guid>https://dev.to/gurpreet_d921f9fff6fa7442/why-im-starting-my-debt-free-journey-while-learning-to-code-2g6p</guid>
      <description>&lt;p&gt;I’ve always believed growth happens when you face your truth — and here’s mine: I have debt, and I’m determined to clear it.&lt;/p&gt;

&lt;p&gt;As a single mom and computer science graduate, my days are a mix of cooking, teaching my daughter, managing bills, and now… learning DSA (Data Structures &amp;amp; Algorithms).&lt;/p&gt;

&lt;p&gt;I started this blog to document two parallel journeys — becoming debt-free and becoming a better coder. Both require discipline, patience, and problem-solving.&lt;/p&gt;

&lt;p&gt;Some days, the numbers in my bank app look as confusing as a nested loop — but just like in coding, I’m learning to break big problems into smaller ones.&lt;/p&gt;

&lt;p&gt;Every post here will be an honest update — about my progress, my struggles, and small victories. If you’re trying to improve your finances or tech skills too, let’s walk this path together. 💪&lt;/p&gt;

&lt;p&gt;Here’s to coding cleaner — and living freer.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>learning</category>
      <category>motivation</category>
    </item>
  </channel>
</rss>
