Reputation: 2030
I want the map to give copies of its values and views, so the entries can't be accidentally modified in any way. Is there such implementation? I have looked into Guava's instances but haven't found what I want yet.
Upvotes: 0
Views: 91
Reputation: 81761
What kind of objects are you planning to put in the map? You're best off with Guava's ImmutableMap (usage example) and immutable keys and values.
Read e.g. Item 15, "Minimize mutability", in Effective Java (2nd ed) by Joshua Bloch for background info. Bloch provides practical advice about implementing immutable classes and justification as to why immutability is a good idea: "Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure."
If you put mutable objects in your (immutable) map, users of the map can still change those objects (even though the mappings remain constant), and you can't really do anything about that (as Jack pointed out).
Upvotes: 0
Reputation: 2073
To have a unmodifiable Map, you can use the Collection.unmodifiableMap function. If you want an immutable map, you have to map the map's keys and values too. This can be done by either using interfaces where not setter is defined or by copying the keys and values to a implementation that does not allow to modify the data.
In my opinion,it is better to hand out copys, so that changes to the copy of the map does not change the original map. This technique is called defensive copy.
Upvotes: 0
Reputation: 133587
There is no direct way of doing it, a Map stores references by value to objects, once you obtain an element through
Value v = map.get(key)
there is no way for the map to disallow modification of the object.
There are two choices, you can return a copy of the object for each get called, which could be inefficient according to how much often you fetch data from the map, eg:
public class MyMap<K,V> extends HashMap<K,V> {
@Override
public V get(K key) {
V v = super.get(key);
return v != null ? v.clone() : null;
}
Or you provide a custom object which can't be modified because there is no way to do it, eg:
class Value {
public final Field1 field1;
public final Field2 field2;
public Value(Field1 field1, Field2 field2) {
this.field1 = field1;
this.field2 = field2;
}
}
But this will allow to modify field1
contents if you don't apply the same methodology to each contained member variable recursively.
Upvotes: 1