Is there java.util.concurrent equivalent for WeakHashMap?

JavaCollectionsGuavajava.util.concurrentWeakhashmap

Java Problem Overview


Can the following piece of code be rewritten w/o using Collections.synchronizedMap() yet maintaining correctness at concurrency?

Collections.synchronizedMap(new WeakHashMap<Class, Object>());

i.e. is there something from java.util.concurrent one can use instead? Note that merely replacing with

new ConcurrentHashMap<Class, Object>(new WeakHashMap<Class, Object>()));

obviously won't work

Java Solutions


Solution 1 - Java

Guava's CacheBuilder class allows you to do this easily.

CacheBuilder.newBuilder().weakKeys().build()

Note that this changes key equality semantics to be == instead of .equals() which will not matter in your case of using Class instances but is a potential pitfall.

Solution 2 - Java

I don't believe there is. In fact the javadoc suggests using Collections.synchronizedMap()

"Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap method."

Solution 3 - Java

Cafeine is a popular competitor of Guava cache.

- keys automatically wrapped in weak references
- values automatically wrapped in weak or soft references

usage:

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
 .weakKeys()
 .weakValues()
 .build(key -> createExpensiveGraph(key));

Solution 4 - Java

> Does wrapping the WeakHashMap in a synchronized map still work > correctly for what you want to do, since the garbage collector can > modify the weakreferences directly at anytime, bypassing the > synchronized map wrapper? I think WeakHashMap only truly works in a > single threaded model.

As mentioned above, the documentation for WeakHashMap at https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html specifically says:

> "A synchronized WeakHashMap may be constructed using the > Collections.synchronizedMap method"

Which implies to me that this technique must work in tandem with the garbage collector's behavior (unless the documentation is buggy!)

Solution 5 - Java

If you are using Java 7 and above, this use case is solved in a thread-safe manner with ClassValue https://docs.oracle.com/javase/7/docs/api/java/lang/ClassValue.html If you require the use of remove, think carefully about concurrency and read the doc thoroughly.

If you are using Java 6 or below. No, you have to synchronize a WeakHashMap.

Solution 6 - Java

If you happen to have the Spring Framework in your classpath already, then one option is ConcurrentReferenceHashMap:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/ConcurrentReferenceHashMap.html

You can choose between using weak or soft references (for both the keys and values).

Solution 7 - Java

Does wrapping the WeakHashMap in a synchronized map still work correctly for what you want to do, since the garbage collector can modify the weakreferences directly at anytime, bypassing the synchronized map wrapper? I think WeakHashMap only truly works in a single threaded model.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNikitaView Question on Stackoverflow
Solution 1 - JavaSteven SchlanskerView Answer on Stackoverflow
Solution 2 - JavaobjectsView Answer on Stackoverflow
Solution 3 - JavaWaldemar WosińskiView Answer on Stackoverflow
Solution 4 - JavaSlim DuikerView Answer on Stackoverflow
Solution 5 - JavaScott CareyView Answer on Stackoverflow
Solution 6 - JavaThomas GLView Answer on Stackoverflow
Solution 7 - JavaGeneView Answer on Stackoverflow