Before HashMap
and the Java Collections Framework revolutionized data handling, Java provided Hashtable
and Properties
classes for key-value mapping. Though largely considered legacy, these classes still play a role in configuration management and backward compatibility.
In this tutorial, you'll learn how Hashtable
and Properties
work, how they differ from modern collections, when to use them (or not), and how to modernize legacy codebases using Java 8+ best practices.
Table of Contents
- What are Hashtable and Properties?
- Java Syntax and Class Structure
- Internal Working and Thread-Safety Model
- Performance Benchmarks and Big-O Complexity
- Real-World Use Cases in Legacy and Modern Code
- Functional Programming in Java 8+
- Java Version Enhancements (Java 8–21)
- Comparisons with Other Maps
- Pros and Cons
- Anti-patterns and Misuse Cases
- Refactoring Legacy Code
- Best Practices
- 📌 What's New in Java [version]?
- Conclusion and Key Takeaways
- FAQ – 10 Expert-Level Questions
What are Hashtable and Properties?
Hashtable
- Part of the original Java 1.0 release
- Implements
Map<K, V>
interface (since Java 2) - Synchronized by default → thread-safe
Properties
- Subclass of
Hashtable<Object, Object>
- Specializes in managing configuration with
String
keys and values - Commonly used for
.properties
file handling
Properties config = new Properties();
config.setProperty("host", "localhost");
String host = config.getProperty("host");
Java Syntax and Class Structure
Hashtable<String, Integer> table = new Hashtable<>();
table.put("A", 1);
table.get("A");
Properties props = new Properties();
props.setProperty("key", "value");
Internal Working and Thread-Safety Model
Hashtable
- Internally uses an array of buckets + chaining (linked list)
- Synchronized methods: every operation locks the entire object
- Resize logic similar to
HashMap
(but less optimized)
Properties
- Extends
Hashtable<Object, Object>
- Offers
load()
andstore()
methods to read/write.properties
files
props.load(new FileReader("config.properties"));
props.store(new FileWriter("config.properties"), "App Config");
Performance Benchmarks
Operation | Hashtable | HashMap | ConcurrentHashMap |
---|---|---|---|
get/put | O(1) | O(1) | O(1) (segmented) |
Synchronization | Full | None | Fine-grained |
Usage | Legacy | General use | Multi-threaded env |
Real-World Use Cases
- Reading Java configuration files (Properties)
- Legacy enterprise codebases (Hashtable)
- Java desktop apps using
.properties
for UI strings
Functional Programming Support
While Hashtable
supports the Map
interface, it is less optimized for modern idioms. Example with Java 8:
Hashtable<String, Integer> table = new Hashtable<>();
table.put("X", 1);
table.put("Y", 2);
table.forEach((k, v) -> System.out.println(k + " = " + v));
Java Version Enhancements
Java 8
- Stream API applies to
entrySet()
forEach()
,compute()
, etc., work onHashtable
Java 9+
Map.of()
offers better alternatives for static configProperties
enhancements remain minimal
Java 10–21
- No major changes to these legacy classes
- Still supported for backward compatibility
Comparisons with Other Maps
Feature | Hashtable | HashMap | Properties |
---|---|---|---|
Thread-safe | Yes (full sync) | No | Yes |
Null keys/values | None allowed | One null key, many null values | No nulls |
Performance | Slower | Fast | Slower |
Usage | Legacy code | Modern standard | Config handling |
Pros and Cons
✅ Pros
- Simple, familiar for legacy codebases
Properties
is great for config files- Thread-safe without extra wrappers
❌ Cons
- Slower due to global synchronization
- Not optimized for modern performance needs
- Doesn't support nulls (adds boilerplate)
Anti-patterns and Misuse Cases
❌ Using Hashtable for new code
Use HashMap
or ConcurrentHashMap
instead.
❌ Storing non-string values in Properties
props.put("port", 8080); // Incorrect: should use setProperty()
❌ Using Hashtable
in high-throughput systems
Rewriting with ConcurrentHashMap
is recommended.
Refactoring Legacy Code
Before:
Hashtable<String, String> users = new Hashtable<>();
After (modern):
Map<String, String> users = Collections.synchronizedMap(new HashMap<>());
Or better for concurrency:
Map<String, String> users = new ConcurrentHashMap<>();
Best Practices
- Prefer
HashMap
orConcurrentHashMap
unless legacy compatibility is needed - Use
Properties
strictly for loading/saving config files - Always wrap
FileReader
/Writer
in try-with-resources
📌 What's New in Java [version]?
Java 8
- Added
forEach()
,compute()
,merge()
to Map interface
Java 9
Map.of()
as alternative toProperties
for static config
Java 10+
var
for local variable declarations
Java 21
- No specific enhancements to
Hashtable
orProperties
Conclusion and Key Takeaways
Hashtable
andProperties
are part of Java’s legacy Map infrastructure.- Still useful for maintaining compatibility or handling simple configuration.
- Should be avoided in new development in favor of more modern, performant alternatives.
- Java 8+ features make transition easier with minimal code rewrite.
FAQ – 10 Expert-Level Questions
1. Why use Hashtable
instead of HashMap
?
Only if legacy compatibility or full synchronization is required.
2. Is Hashtable
faster than ConcurrentHashMap
?
No. ConcurrentHashMap
is more scalable under concurrency.
3. Can Properties
hold non-String types?
It can, but getProperty()
only works for strings. Use carefully.
4. Can Hashtable
store null keys or values?
No. Both keys and values must be non-null.
5. How is Properties
used in Spring or Java EE?
Frequently used to externalize configuration (application.properties
).
6. Can I iterate Properties
like a map?
Yes, via entrySet()
inherited from Hashtable
.
7. What's the best alternative to Hashtable
?
Use ConcurrentHashMap
for thread safety, or HashMap
otherwise.
8. Are Properties
files Unicode-compatible?
Yes, but escaped via \uXXXX
format when saved in ISO-8859-1.
9. How to read from a .properties
file safely?
Use try-with-resources and catch IOException
.
10. Should I remove all Hashtable
usage in codebase?
Yes, unless a third-party library depends on it. Refactor using modern collections.