23

How do I get a ConcurrentHashMap with weak keys and identity hashes in Java? I think Google Guava Collections can give such a thing, but can I get it from the standard library? What other options do I have?

r.v
  • 4,697
  • 6
  • 35
  • 57

4 Answers4

15

I think Google Guava Collections can give such a thing, but can I get it from the standard library?

The short answer to that is No. Java SE does not implement this particular combination.

  • You could instantiate a java.util.concurrent.ConcurrentHashMap with WeakReference keys, and do some extra work to implement removal of map entries for broken references, but that won't give you identity hash semantics.

  • You could instantiate a java.util.IdentityHashMap with WeakReference keys, and do some extra work to implement removal of map entries for broken references, but that won't give you concurrent behaviour.

  • Using a java.util.WeakHashMap won't give you either concurrency or identity hashing.

  • You could (in theory) wrap the key class in something that overrode the natural equals and hashcode methods. But that is most likely to be unusable.

  • I don't think it would be possible to do this by overriding methods in either ConcurrentHashMap or IdentityHashMap.


Maybe the only viable option would be to change the key classes equals and hashcode methods to be identity based. But that won't work for "built in" key types (especially final ones) or for cases where you need value-based equals/hashcode in other parts of the application.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Any comments about possible options? – r.v Mar 17 '13 at 02:08
  • 1
    Use Google Guava. That's an option. (Any reason not to use it?) Or write your own implementation from scratch. – Stephen C Mar 17 '13 at 02:09
  • Regarding performance of the required map from Guava, will it be the same as `java.util.concurrent.ConcurrentHashMap`? – r.v Mar 17 '13 at 02:13
  • I found myself: "The returned map is implemented as a hash table with similar performance characteristics to ConcurrentHashMap" at http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/index.html – r.v Mar 17 '13 at 02:50
  • WeakReferences can be extended. Can you override the equals/hashcode to deal with identity using System.identityHashcode()? – Michael Deardeuff Mar 17 '13 at 06:59
  • 1
    Please, for the love of people that come after you, don't write your own from scratch. Use Guava. – Steven Schlansker Mar 17 '13 at 07:32
  • @MichaelDeardeuff, the purpose is a little different. This is a cache-like data structure where I want to store properties of *arbitrary* objects as long as they are in memory. Thanks anyway. – r.v Mar 17 '13 at 17:29
  • @StevenSchlansker sure no plans to write from scratch. – r.v Mar 17 '13 at 17:29
  • @r.v that is exactly what I was talking about. But I'm with the others; use guava – Michael Deardeuff Mar 18 '13 at 19:17
  • How to instantiate a java.util.concurrent.ConcurrentHashMap with WeakReference. Any example – Souvik Aug 19 '13 at 19:56
  • 3
    @Souvik `new MapMaker().weakKeys().makeMap()`. See the [apidoc](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker.html). This uses Guava and is not exactly `java.util.concurrent.ConcurrentHashMap` but will be a drop-in replacement. – r.v Aug 31 '13 at 00:43
  • @Souvik for the more cumbersome standard-library only solution, the instantiation would be `new java.util.concurrent.ConcurrentHashMap,V>()` where `K` and `V` are the key and value types respectively. Of course, you would also need some boilerplate with this to convert keys to weak refs before insertion and to remove from the map the keys that get garbage collected. – r.v Aug 31 '13 at 00:52
  • is there any options without using Guava? – Sibelius Seraphini Nov 23 '15 at 17:11
  • @SibeliusSeraphini - Yes. Read through the comments above yours. – Stephen C Mar 07 '16 at 21:45
  • 1
    All the work arounds in these comments are wrong. Guava doesn't compare WeakReferences by the identity of the referent value, it compares by the identity of the WeakReference, which is new every time. So it won't work. It's basically useless, truthfully. ConcurrentHashMap, V> has the same issue. – DoctorPangloss Dec 08 '20 at 17:23
5

The Google Guava implementation appears the easiest way to go. One may initialize the required map with new MapMaker().weakKeys().makeMap() and use just as one would use java.util.concurrent.ConcurrentHashMap. See the apidoc for more details.

jaco0646
  • 15,303
  • 7
  • 59
  • 83
r.v
  • 4,697
  • 6
  • 35
  • 57
  • That's correct – why was it downvoted? You should mentiont that using weak keys causes key equality to be evaluated with `==`. – Laurent Caillette May 25 '17 at 22:39
  • @LaurentCaillette It was probably downvoted because OP specifically asked for a solution that does not use a 3rd-party library – Gili May 15 '18 at 14:11
  • It was downvoted because evaluating key equality with == on WeakReference makes it basically useless. – DoctorPangloss Dec 08 '20 at 17:28
2

search ConcurrentWeakIdentityHashMap, you will get many examples. I wrote an implement myself, for I think the hashCode of org/ehcache/core/internal/util/ConcurrentWeakIdentityHashMap$WeakReference is so bad.

Example of ehcache3

Example I wrote

Pull Rquest to fix the ehcache3 ConcurrentWeakIdentityHashMap Key hashCode

martian
  • 519
  • 1
  • 6
  • 16
  • Thanks for the second link. It solves many of my probles. Works like a charm in my AI project. Had to change class scope and constructors to public though – Tschallacka Apr 26 '17 at 22:52
2

if your application is under spring framework ( version is gt 3.2 ), you can consider to use org.springframework.util.ConcurrentReferenceHashMap. Below is its description:

A ConcurrentHashMap that uses soft or weak references for both keys and values. This class can be used as an alternative to Collections.synchronizedMap(new WeakHashMap>()) in order to support better performance when accessed concurrently. This implementation follows the same design constraints as ConcurrentHashMap with the exception that null values and null keys are supported.

NOTE: The use of references means that there is no guarantee that items placed into the map will be subsequently available. The garbage collector may discard references at any time, so it may appear that an unknown thread is silently removing entries.

If not explicitly specified, this implementation will use soft entry references.

Sheldon Wei
  • 1,198
  • 16
  • 31
  • The OP asks for a Map with three characteristics: _1._ Concurrency _2._ Weak Keys _3._ Identity Hash. Spring only provides the first two with its `ConcurrentReferenceHashMap`. – jaco0646 Jun 07 '20 at 13:20
  • 1
    ConcurrentReferenceHashMap also has weak values. It will remove an entry if the value has no hard references anywhere. – Frettman Dec 02 '20 at 14:34