The Google Collections Library, Page 4
The ReferenceMap is quite a specialized class, but nonetheless an extremely useful one. If you ever write a cache implementation of some kind, ReferenceMap will be your best friend.
Caches, or weak reference maps, are an easy way to shortcut work in an application. Instead of looking up an item repeatedly from a slow or expensive source like a database, once you have found it the first time, you could put it into a WeakHashMap and for future lookups you could attempt to see whether there is a match in the WeakHashMap already. Because the keys in a WeakHashMap are weakly referenced, if there are no other strong references to the key at garbage collection time, the value can be removed from the heap and the space recovered, whereupon the entry in the map simply disappears.
It is also based on ConcurrentMap, making it ideal for use in concurrent systems. In fact, a Strong:Strong instance of ReferenceMap is semantically identical to ConcurrentMap, and a Weak:Strong instance is practically a drop-in replacement for WeakHashMap. Any other combination also can be used, and if either the key or the value is reclaimed, the item is removed from ReferenceMap.
There are also Soft references. Although the specification of Soft references is itself rather soft, the intention is that a Soft reference is a little stronger than a Weak one. In the case of a Weak reference, the entry is removed whenever a garbage collection event happens and there are no strong references to the object. In the case of a Soft reference, the object may be retained until the resources are needed; in other words, it might not be garbage collected until heap space starts to run low, holding it cached for as long as possible. This is down to the implementation of the VM in question, however, and often the VMs still seem fairly eager to collect Soft references as well.
An example initialization might look like this:
new ReferenceMap<String, Integer>(ReferenceType.WEAK, ReferenceType.SOFT);
When the Java collections framework was created, it introduced a way to return unmodifiable collections. That is, wrappers were put around collections to prevent unintentional modification of the contents of those collections.
However, unmodifiable collections have one flaw: They can change. Even though the recipient of the unmodifiable collection cannot change the contents, the original collection on which the unmodifiable one is based can still be changed, and this affects the unmodifiable collection because they are sharing the backing collection.
In other words, a programmer might incorrectly assume that the unmodifiable collection they have cannot change. This is not true.
The Google collections library introduces Immutable collections as an alternative. These take a copy of the original collection and then make it immutable, so that a recipient can rely on that collection never changing.
final List<String> immutableList = Lists.immutableList("Hello", "World"); // UnsupportedOperationException! immutableList.add("!");
And, to contrast the Java unmodifiableList with the Google Collections Library immutableList:
final List<String> baseList = Lists.newArrayList("Hello", "World"); final List<String> unmodifiableList = Collections.unmodifiableList(baseList); final List<String> immutableList = Lists.immutableList(baseList); baseList.add("!"); // modify the original list // prints [Hello, World, !] - changed System.out.println(unmodifiableList); // prints [Hello, World] - unchanged System.out.println(immutableList);
This is often a very good combination with a final reference to the immutable collection, but there is still danger! Even though the collection itself cannot be altered (in other words, elements cannot be added, removed, or replaced), any mutable objects stored in the collection can still be modified! For this reason, it is recommended that mutable values should not be stored in immutable collections, because it could cause a great deal of confusion and much of the benefit of using an immutable collection will be lost. Of course, there are always exceptions, but if you do choose to mix mutable and immutable, you had better be pretty good at documenting the reasons and consequences.
Page 4 of 6