Alexiy
Alexiy

Reputation: 2030

A map whose contents don't change

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

Answers (3)

Jonik
Jonik

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

Hannes
Hannes

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

Jack
Jack

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

Related Questions