Firstly, you shouldn't use Hashtable
class - it's legacy. If you need a general purpose implementation of the Map
interface, use HashMap
instead.
In case when you need to initialize a general purpose Map
with a few entries, you can use one of the overloaded versions of Map.of()
method which is available starting with Java 9. It allows providing up to 10
key-value pairs, if you need more you can use Map.ofEntries()
, which takes a varargs of map entries. You can create a map entry using another Java 9 method Map.entry()
.
Example:
public static final Map<String, Integer> numbers =
Map.of("one", 1, "two", 2, "three", 3);
Note these maps are
1. Immutable, therefore it would be the right choice only if the data never change (or might change rarely, i.e. in case of very frequent reads and infrequent writes, and every write would require re-initializing the map).
2 So-called unmodifiable maps like MapN
(which is an internal implementation used by Map.ofEntries()
intended to store an arbitrary number of key-value pairs) are optimized in terms of Memory consumption, their underlying array occupies exactly as match space as match there are key-value pairs and no more, and retrieving a value from an unmodifiable map using get()
might even perform slightly better (see the quote below) in comparison to a HashMap
.
For more information you can refer to official documentation - Creating Immutable Lists, Sets, and Maps:
Use Cases
The common use case for the immutable methods is a collection that is
initialized from known values, and that never changes. Also consider
using these methods if your data changes infrequently.
For optimal performance, the immutable collections store a data set
that never changes. However, you may be able to take advantage of the
performance and space-saving benefits even if your data is subject to
change. These collections may provide better performance than the
mutable collections, even if your data changes occasionally.
If you have a large number of values, you may consider storing them in
a HashMap. If you are constantly adding and removing entries, then
this is a good choice. But, if you have a set of values that never
change, or rarely change, and you read from that set a lot, then the
immutable Map is a more efficient choice. If the data set is read
frequently, and the values change only rarely, then you may find that
the overall speed is faster, even when you include the performance
impact of destroying and rebuilding an immutable Map when a value
changes.
Also note that depending on the type of keys and the actual data (specifically on the number of collisions), an unmodifiable map might perform worse than a HashMap
because contrary to HashMap
unmodifiable map is incapable to store and reuse hashes of the keys and hence might perform more comparisons of keys using equals
method. And in case of large number of collisions, unmodifiable map has no means to mitigate performance degradation, unlike HashMap
which since would try to arrange nodes into a tree when the number of nodes in a bucket exceeds certain threshold.
Spiking of other alternatives doubly-brace initialization, which creates an instance of anonymous inner class, is indisputably a discouraged practice.
Static and instance initializer blocks have no downsides from the technical point of view, they allow you to keep the variables final
if you need that. But some might argue that from the perspective of clean coding, initializer blocks are not very great.
Another possibility you might consider is to initialize a map inline using Stream API (for instance, when map-data can be expressed as a sequence that is easy to generate).