Can someone explain to me when it is useful to use MapMaker or WeakHashMaps?
I have read many people really like the MapMaker of Google Guava (Collections), however I cannot see any good uses of it.
I have read the javadoc, and it says that it behaves like ConcurrentHashMap. It also says new MapMaker().weakKeys().makeMap()
can almost always be used as a drop-in replacement for WeakHashMap.
However, reading the javadocs of ConcurrentHashMap and WeakHashMap makes me wonder when it is useful to use it? It seems to me that yo开发者_C百科u cannot have a guarantee that whatever you put in the map will be there, or have I misunderstood?
The thing about MapMaker
is that there are many options for the kind of map you build, which enables those maps to serve many purposes.
- Dirk gives a good example of a use for weak keys.
- Soft values are useful for caching, as you can cache values in the map without worrying about running out of memory since the system is free to evict entries from the cache if it needs memory.
- You can choose to have entries expire after a certain amount of time. This is also useful for caching, since you may want certain data cached for a specific period of time before doing an expensive operation to update it.
- One of my favorite things is making a computing map. A computing map uses a
Function<K, V>
to automatically retrieve the value associated with a given key if it isn't already in the map. This combines well with soft values and/or expiration times. After an entry is evicted by the map (due to memory demand or expiration), the next time the value associated with that key is requested it will automatically be retrieved and cached in the map once more.
...and that's somewhat the point of it. Weak references are useful, if you don't want to (or cannot afford to) retain an object indefinetly in memory. Consider the following use case: you need to associate information with classes. Now, since you are running in an environment, where classes might get reloaded (say, a Tomcat, or OSGi environment), you want the garbage collector to be able to reclaim old versions of a class as soon as it deems safe to do so.
An initial attempt to implement this, might look like
class ClassAssoc {
private final IdentityHashMap<Class<?>,MyMetaData> cache = new ...;
}
The problem here is: this would keep all classes in the cache
member forever (or at least, unless they are manually removed), forcing the garbage collector to retain them indefinitly, including everything referenced from the class (static member values, class loader information, ...)
By using weak references, the garbage collector can reclaim old version of the class as soon as no other references to it (usually instances) exist. On the other hand: as long as such references exist, the value is guaranteed to be also reachable from the weak reference object, and thus, is a valid key in the cache table.
Add concurrency and other atrocities to the picture, and you are at what MapMaker
optionally also provides...
A WeakHashmap
entry will be kept in the map while someone (other than the map) is referencing the entry. If nobody else thant the map is keeping a reference on the entry, then the entry can be removed on a next GC run.
ConcurrentHashMap
is a Map
which may be safely used in multi-threading environment. It is better than synchronized version of regular Map
because concurrency means that different threads are often available to access this map without blocking.
精彩评论