HashMap Data Structure in Java: Fundamentals and Usage

HashMap vs Hashtable

Key Differences

  • Thread Safety: Hashtable is synchronized, while HashMap is not
  • Null Values: HashMap allows one null key and multiple null values; Hashtable prohibits null keys and values
  • Performance: HashMap generally performs better in single-threaded environments due to lack of synchronization overhead

HashMap Fundamentals

HashMap is a widely used collection class in Java that implements the Map interface. It extends AbstractMap and implements the Map, Cloneable, and Serializable interfaces.

Class Hierarchy

java.lang.Object
  java.util.AbstractMap
    java.util.HashMap
Type Parameters: - K - the type of keys maintained by this map - V - the type of mapped values All Implemented Interfaces: - Serializable, Cloneable, Map Direct Known Subclasses: - LinkedHashMap, PrinterStateReasons

Primitive Types and Wrapper Classes

Primitive Type Reference Type
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character

Common Operations

Creating a HashMap

import java.util.HashMap;
HashMap<Integer, String> fruitMap = new HashMap<Integer, String>();

Adding Elements

The put() method uses hashCode() to determine the bucket position for storing key-value pairs.

public class HashMapDemo {
    public static void main(String[] args) {
        HashMap<Integer, String> fruitMap = new HashMap<Integer, String>();
        fruitMap.put(1, "Apple");
        fruitMap.put(2, "Banana");
        System.out.println(fruitMap);
    }
}

Accessing Elements

The get(key) method retrieves values using the key's hashCode to locate the appropriate bucket.

public class HashMapAccess {
    public static void main(String[] args) {
        HashMap<Integer, String> fruitMap = new HashMap<Integer, String>();
        fruitMap.put(1, "Apple");
        fruitMap.put(2, "Banana");
        System.out.println(fruitMap.get(1));
    }
}

Removing Elements

public class HashMapRemove {
    public static void main(String[] args) {
        HashMap<Integer, String> fruitMap = new HashMap<Integer, String>();
        fruitMap.put(1, "Apple");
        fruitMap.put(2, "Banana");
        fruitMap.remove(1);
        fruitMap.clear();
    }
}

Counting Elements

The size() method returns the number of key-value pairs in the HashMap.

Iterating Through HashMap

// Method 1: Using keySet()
Iterator<String> keyIterator = fruitMap.keySet().iterator();
while (keyIterator.hasNext()) {
    String key = keyIterator.next();
    System.out.println(key + "=" + fruitMap.get(key));
}

// Method 2: Using entrySet()
Iterator<Map.Entry<String, Integer>> entryIterator = fruitMap.entrySet().iterator();
while (entryIterator.hasNext()) {
    Map.Entry<String, Integer> entry = entryIterator.next();
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println(key + "=" + value);
}

HashMap Constructors and Internal Variables

Constructors

Default Constructor

public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
}

Creates an empty HashMap with default initial capacity (16) and load factor (0.75).

Capacity-Specified Constructor

public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

Creates an empty HashMap with specified initial capacity and default load factor.

Full Parameter Constructor

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);
}

Creates an empty HashMap with specified capacity and load factor.

Map-Based Constructor

public HashMap(Map<? extends K, ? extends V> m) {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    putMapEntries(m, false);
}

Creates a new HashMap with the same mappings as the specified Map.

Internal Variables

  • DEFAULT_INITIAL_CAPACITY = 16 (must be a power of two)
  • MAXIMUM_CAPACITY = 1 << 30
  • DEFAULT_LOAD_FACTOR = 0.75f
  • TREEIFY_THRESHOLD = 8 (converts linked list to tree when exceeded)
  • UNTREEIFY_THRESHOLD = 6 (converts tree back to list when below this)
  • MIN_TREEIFY_CAPACITY = 64 (minimum capacity before tree conversion)
  • table - array storing elements (always power of two size)
  • entrySet - collection containing map entries
  • size - number of key-value pairs
  • modCount - counter for structural modifications
  • threshold - capacity threshold for resizing
  • loadFactor - actual load factor

Key Performance Factors

Initial Capacity and Load Factor

These two factors significantly impact HashMap performance:

  • Initial Capacity: The capacity when the HashMap is created
  • Load Factor: Determines when the HashMap should be resized (default 0.75)

Collision Handling

HashMap handles collisions through:

  • Linked lists for small collision chains
  • Red-black trees for longer collision chains (when length exceeds TREEIFY_THRESHOLD)

Internal Data Structure

HashMap uses an array of nodes, where each node can be part of a linked list or a red-black tree depending on collision patterns.

Hashing Algorithm

HashMap uses a combination of key's hashCode() and additional bit manipulation to determine bucket positions, ensuring even distribution of entries.

Tags: java hashmap Data Structures Hash Table Collections

Posted on Thu, 14 May 2026 08:22:06 +0000 by harrylt