Of course! In Java, the term "dictionary" isn't a built-in class. Instead, it refers to a general concept of a data structure that stores key-value pairs. You look up a value using its unique key.

The primary and most common interface for this in Java is the java.util.Map interface. The most frequently used implementation of Map is HashMap.
Let's break it down, starting from the most common approach and covering other important types.
The Main Player: Map Interface and HashMap
This is the go-to for most situations where you need a dictionary.
Key Characteristics of HashMap:
- Unordered: The elements are not stored in any predictable order (neither insertion order nor sorted order).
- Fast Lookups, Insertions, and Deletions: On average, these operations take constant time, O(1).
- Allows one
nullkey and multiplenullvalues. - Not Synchronized: It is not thread-safe. If multiple threads modify a
HashMapconcurrently, you must synchronize it externally.
How to Use HashMap (The Classic Way)
Here's a complete, runnable example.

import java.util.HashMap;
import java.util.Map;
public class JavaDictionaryExample {
public static void main(String[] args) {
// 1. Create a HashMap (the dictionary)
// The syntax is Map<KeyType, ValueType>
Map<String, Integer> wordCount = new HashMap<>();
// 2. Add key-value pairs (put)
wordCount.put("apple", 5);
wordCount.put("banana", 3);
wordCount.put("orange", 8);
wordCount.put("apple", 10); // This will update the value for "apple" from 5 to 10
System.out.println("Initial dictionary: " + wordCount);
// 3. Get a value by its key (get)
Integer countOfApple = wordCount.get("apple");
System.out.println("Count of 'apple': " + countOfApple); // Output: 10
// 4. Check if a key exists (containsKey)
if (wordCount.containsKey("banana")) {
System.out.println("'banana' is in the dictionary.");
}
// 5. Check if a value exists (containsValue)
if (wordCount.containsValue(8)) {
System.out.println("The value 8 is in the dictionary.");
}
// 6. Remove a key-value pair (remove)
wordCount.remove("orange");
System.out.println("After removing 'orange': " + wordCount);
// 7. Get the size of the dictionary (size)
System.out.println("Size of the dictionary: " + wordCount.size());
// 8. Iterate over the dictionary
System.out.println("\nIterating over the dictionary:");
// Using a for-each loop to get the entries (key-value pairs)
for (Map.Entry<String, Integer> entry : wordCount.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
}
}
Output:
Initial dictionary: {orange=8, banana=3, apple=10}
Count of 'apple': 10
'banana' is in the dictionary.
The value 8 is in the dictionary.
After removing 'orange': {banana=3, apple=10}
Size of the dictionary: 2
Iterating over the dictionary:
Key: banana, Value: 3
Key: apple, Value: 10
Modern Java: Map.of() (For Immutable Dictionaries)
Since Java 9, you can create small, immutable dictionaries (maps) very easily using the Map.of() factory methods. These are great for configuration data that shouldn't change.
import java.util.Map;
public class ImmutableDictionaryExample {
public static void main(String[] args) {
// Create an immutable map with key-value pairs
Map<String, String> countryCapitals = Map.of(
"USA", "Washington D.C.",
"UK", "London",
"Japan", "Tokyo"
);
System.out.println("Immutable map: " + countryCapitals);
// You can still read data
System.out.println("Capital of Japan: " + countryCapitals.get("Japan"));
// But you cannot modify it! The following lines will cause a compilation error.
// countryCapitals.put("France", "Paris"); // -> java.lang.UnsupportedOperationException
// countryCapitals.remove("UK"); // -> java.lang.UnsupportedOperationException
}
}
Other Map Implementations (When to Use What)
Java provides several Map implementations for different needs.
| Implementation | Order | Key Characteristics | When to Use |
|---|---|---|---|
HashMap |
Unordered | Fastest for general-purpose use. Not thread-safe. | The default choice. Use when you don't care about order and need fast performance. |
LinkedHashMap |
Insertion Order | Maintains the order in which keys were inserted. Slightly slower than HashMap. |
When you need to preserve the insertion order of keys (e.g., caching with LRU logic). |
TreeMap |
Sorted (Natural or Custom) | Keys are stored in a sorted tree structure. Slower than HashMap (O(log n)). |
When you need the keys to be sorted (e.g., alphabetical, numerical). |
Hashtable |
Unordered | Legacy class. Synchronized (thread-safe), but slow. Does not allow null keys or values. |
Avoid in new code. Use ConcurrentHashMap for thread-safe maps instead. |
ConcurrentHashMap |
Unordered | High-performance, thread-safe alternative to Hashtable. |
When multiple threads need to read and write to the map concurrently. |
Example: TreeMap for Sorted Data
import java.util.Map;
import java.util.TreeMap;
public class SortedDictionaryExample {
public static void main(String[] args) {
// TreeMap automatically sorts keys based on their natural order (for Strings, alphabetically)
Map<String, Integer> scores = new TreeMap<>();
scores.put("Charlie", 95);
scores.put("Alice", 100);
scores.put("Bob", 85);
System.out.println("Scores in alphabetical order: " + scores);
// Output: Scores in alphabetical order: {Alice=100, Bob=85, Charlie=95}
}
}
Java 8+ Streams and Functional Operations
Modern Java makes working with dictionaries even more powerful using Streams.
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class DictionaryStreamExample {
public static void main(String[] args) {
Map<String, Integer> inventory = new HashMap<>();
inventory.put("apples", 10);
inventory.put("bananas", 25);
inventory.put("oranges", 18);
inventory.put("grapes", 5);
// 1. Filter: Find all fruits with more than 15 items
Map<String, Integer> highStock = inventory.entrySet()
.stream()
.filter(entry -> entry.getValue() > 15)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println("High stock items: " + highStock);
// Output: High stock items: {bananas=25, oranges=18}
// 2. Transform: Create a new map with keys in uppercase
Map<String, Integer> upperCaseInventory = inventory.entrySet()
.stream()
.collect(Collectors.toMap(
entry -> entry.getKey().toUpperCase(), // Key mapper
Map.Entry::getValue // Value mapper
));
System.out.println("Inventory with uppercase keys: " + upperCaseInventory);
// Output: Inventory with uppercase keys: {APPLES=10, BANANAS=25, ORANGES=18, GRAPES=5}
// 3. Calculate: Get the total number of fruits
int totalFruits = inventory.values().stream().mapToInt(Integer::intValue).sum();
System.out.println("Total fruits in inventory: " + totalFruits);
// Output: Total fruits in inventory: 58
}
}
Summary
| If you want a... | Use... | Why? |
|---|---|---|
| Simple, fast, general-purpose dictionary | HashMap |
It's the standard, most efficient choice for most use cases. |
| Dictionary that remembers insertion order | LinkedHashMap |
It's a HashMap with a linked list to track order. |
| Dictionary with sorted keys | TreeMap |
It automatically sorts keys for you. |
| A small, unchangeable dictionary | Map.of() |
It's concise, safe, and easy to read for immutable data. |
| A thread-safe dictionary for concurrent access | ConcurrentHashMap |
It's highly optimized for multi-threaded environments. |
