How to directly initialize a Java HashMap with literal values?
What is the correct syntax for initializing a Java HashMap with initial values directly, similar to this attempted code:
Map<String, String> test =
new HashMap<String, String>{"test":"test","test":"test"};
Is this approach possible in Java? I’m looking for the most efficient way to create a HashMap with static, final values that are known at initialization time and won’t change.
Java does not support literal HashMap initialization syntax like other languages. However, there are several approaches to create HashMaps with initial values, with different trade-offs in terms of immutability, performance, and code readability.
Contents
- Traditional Static Block Initialization
- Double Brace Initialization (Anti-Pattern)
- Java 9+ Literal Syntax with Map.of()
- Guava Library Alternative
- Static Final Best Practices
- Performance Comparison
Traditional Static Block Initialization
The most reliable approach for static final HashMap initialization in all Java versions is using a static initializer block:
import java.util.HashMap;
import java.util.Map;
public class MapInitializer {
private static final Map<String, String> TEST_MAP;
static {
Map<String, String> temp = new HashMap<>();
temp.put("test", "test");
temp.put("test1", "test2");
TEST_MAP = Collections.unmodifiableMap(temp);
}
}
This approach provides:
- Full compatibility with Java 8 and earlier
- Explicit control over the initialization process
- Immutability through
Collections.unmodifiableMap() - Clean separation of declaration and initialization
The static block ensures the map is initialized exactly once when the class is loaded, making it thread-safe for static final fields.
Double Brace Initialization (Anti-Pattern)
You may encounter double brace initialization, but it’s generally discouraged:
Map<String, String> map = new HashMap<String, String>() {{
put("key1", "value1");
put("key2", "value2");
}};
Why this is problematic:
- Creates an anonymous inner class for each usage
- Holds hidden references to the enclosing object
- Can cause memory leaks
- Performance overhead due to extra class creation
- Considered an anti-pattern in production code
While it works for simple cases, avoid this pattern in production code due to its significant drawbacks.
Java 9+ Literal Syntax with Map.of()
Starting with Java 9, the Java platform provides literal-like syntax for creating immutable maps:
import java.util.Map;
// Java 9+ immutable map with literal-like syntax
private static final Map<String, String> TEST_MAP = Map.of(
"key1", "value1",
"key2", "value2",
"key3", "value3"
);
// For more than 10 entries, use Map.ofEntries()
private static final Map<String, String> LARGE_MAP = Map.ofEntries(
Map.entry("key1", "value1"),
Map.entry("key2", "value2"),
Map.entry("key3", "value3")
);
Advantages of Java 9+ approach:
- Clean syntax that resembles literal initialization
- Immutable by default - no need for Collections.unmodifiableMap()
- Type-safe with compile-time checking
- No performance overhead compared to traditional methods
- No memory leaks from anonymous inner classes
Limitations:
- Only available in Java 9 and later
- Maps created this way are immutable
- Limited to 10 key-value pairs in Map.of(); use Map.ofEntries() for larger maps
Guava Library Alternative
For projects using Google Guava, you can achieve literal-like initialization:
import com.google.common.collect.ImmutableMap;
import java.util.Map;
private static final Map<String, String> TEST_MAP =
ImmutableMap.of("key1", "value1", "key2", "value2");
Benefits:
- Clean syntax similar to Java 9’s Map.of()
- Available in Java 8 and earlier
- Immutable by default
- Well-tested and widely used
Considerations:
- Adds external dependency to your project
- Slightly larger binary size due to Guava library
Static Final Best Practices
For static final HashMap initialization, follow these best practices:
For Java 9+ Projects
import java.util.Map;
public class Config {
// Perfect for small maps (≤ 10 entries)
private static final Map<String, String> SMALL_CONFIG = Map.of(
"host", "localhost",
"port", "8080",
"timeout", "30"
);
// For larger maps
private static final Map<String, String> LARGE_CONFIG = Map.ofEntries(
Map.entry("db.url", "jdbc:mysql://localhost:3306/mydb"),
Map.entry("db.user", "admin"),
Map.entry("db.password", "secret")
);
}
For Java 8 Projects
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class LegacyConfig {
private static final Map<String, String> CONFIG;
static {
Map<String, String> temp = new HashMap<>();
temp.put("host", "localhost");
temp.put("port", "8080");
temp.put("timeout", "30");
CONFIG = Collections.unmodifiableMap(temp);
}
}
Key considerations:
- Always make static maps final when possible
- Use immutability to prevent accidental modification
- Consider thread-safety - immutable maps are inherently thread-safe
- Document the map’s purpose and expected usage
Performance Comparison
| Approach | Memory Overhead | Performance | Immutability | Java Version |
|---|---|---|---|---|
| Static Block | Low | Excellent | ✓ | All versions |
| Double Brace | High (anonymous class) | Poor | ✓ | All versions |
| Map.of() (Java 9+) | Low | Excellent | ✓ | Java 9+ |
| Guava ImmutableMap | Medium | Good | ✓ | Java 8+ |
Recommendations:
- Java 9+: Use
Map.of()orMap.ofEntries()for clean, performant immutable maps - Java 8: Use static blocks with
Collections.unmodifiableMap() - Testing: Avoid double brace initialization in production code
- Large projects: Consider Guava if you need Java 8 compatibility with clean syntax
Sources
- Stack Overflow - How to directly initialize a HashMap (in a literal way)?
- Java67 - How to initialize HashMap with values in Java
- Baeldung - Initialize a HashMap in Java
- Stack Overflow - How can I initialise a static Map?
- Tech Tutorials - How to directly initialize a HashMap
- Sentry - How to directly initialize a HashMap in a literal way in Java
- Gang of Coders - How to directly initialize a HashMap
- Oracle Documentation - Creating Unmodifiable Lists, Sets, and Maps
Conclusion
Java doesn’t support literal HashMap initialization syntax, but offers several excellent alternatives:
- For Java 9+ projects: Use
Map.of()for small maps orMap.ofEntries()for larger ones - these provide clean, immutable, and performant initialization - For Java 8 projects: Use static initializer blocks with
Collections.unmodifiableMap()for thread-safe, immutable maps - Avoid double brace initialization due to its memory and performance issues
- Consider Guava’s ImmutableMap if you need Java 8 compatibility with cleaner syntax
The most efficient approach depends on your Java version and project requirements, but all recommended methods provide immutability and good performance for static final HashMap initialization.