To flesh out the code being hinted at in the accepted answer and comments, here is my own take on the code to get a concurrent weak set.
Java, without Guava
Using the idiom suggested in the class documentation, use Collections.newSetFromMap to wrap a concurrent Map as a Set. The use of Boolean
as the map's Value type is just filler, inconsequential.
Set< YourObjectTypeGoesHere > concurrentWeakSet =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap< YourObjectTypeGoesHere , Boolean >()
)
)
;
The parameterized types can be inferred, simplifying the code to:
Set< YourObjectTypeGoesHere > concurrentWeakSet =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap<>() // Types inferred, so omitted.
)
)
;
Guava
Alternatively, we can use MapMaker
from the Google Guava library.
Instead of using that doc’s example wrapping a WeakHashMap, we substitute the WeakHashMap with a map from Google Guava’s MapMaker per the Guava doc’s suggestion to call new MapMaker().weakKeys().makeMap()
. The Guava doc notes that this map "compares keys using object identity whereas WeakHashMap uses Object.equals
".
Usage
Using it is easier than understanding it!
To Instantiate
To create the concurrent weak set, copy paste the following code. Replace two occurrences of YourObjectTypeGoesHere
.
int level = 16; // Basically, the approximate number of threads that may simultaneously try to mutate the map. See Guava doc.
ConcurrentMap<YourObjectTypeGoesHere , Boolean> concurrentWeakMap = new MapMaker().concurrencyLevel( level ).weakKeys().makeMap(); // Google Guava team recommends MapMaker > weakKeys > makeMap as a replacement for weakHashMap.
Set<YourObjectTypeGoesHere> concurrentWeakSet = Collections.newSetFromMap( concurrentWeakMap ); // Concurrency protection carries over to Set wrapper.
To Add
To add to the set:
concurrentWeakSet.add( myObject );
To Iterate
To access the elements in set:
Iterator<YourObjectTypeGoesHere> iterator = concurrentWeakSet.iterator();
while(iterator.hasNext()) {
YourObjectTypeGoesHere myObject = iterator.next();
if( myObject != null ) { // Not sure if needed. Is it possible for object to be garbage-collected but not yet have its entry removed from the Set/Map?
// Work with the object.
}
}
To Remove
Being weak means there is no need to remove elements. As the elements become disused and garbage-collected, they disappear from our collection (Map/Set).