5

我想要一个对元素的弱引用的并发集合。我想用番石榴做这个MapMaker

Set<Object> concurrentSet = Collections.newSetFromMap(
    new MapMaker<Object, Boolean>().weakKeys().makeMap());

Guava 会自动为您提供带有弱密钥的身份哈希。但是,事实证明MapMaker不允许类型参数。

file.java:123 type com.google.common.collect.MapMaker does not take parameters
                new MapMaker<Object, Boolean>().weakKeys().makeMap());
                            ^

任何解决方案如何获得对元素的弱引用的并发集?

4

3 回答 3

6

为了充实接受的答案和评论中暗示的代码,这是我自己对代码的看法,以获得并发弱集。

Java,没有番石榴

使用类文档中建议的习语,使用Collections.newSetFromMap将并发 Map 包装为 Set。用作Boolean地图的 Value 类型只是填充物,无关紧要。

Set< YourObjectTypeGoesHere > concurrentWeakSet = 
    Collections.synchronizedSet(
        Collections.newSetFromMap(
            new WeakHashMap< YourObjectTypeGoesHere , Boolean >()
        )
    )
;

可以推断参数化类型,将代码简化为:

Set< YourObjectTypeGoesHere > concurrentWeakSet = 
    Collections.synchronizedSet(
        Collections.newSetFromMap(
            new WeakHashMap<>()     // Types inferred, so omitted.
        )
    )
;

番石榴

或者,我们可以MapMaker从 Google Guava 库中使用。

我们没有使用该文档的示例包装WeakHashMap ,而是根据 Guava 文档的建议将WeakHashMap 替换为来自Google GuavaMapMakernew MapMaker().weakKeys().makeMap()的地图 call 。Guava 文档指出,此映射“使用对象标识比较键,而 WeakHashMap 使用Object.equals”。

用法

使用它比理解它更容易!

实例化

要创建并发弱集,请复制粘贴以下代码。替换两次出现的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.

添加

要添加到集合中:

concurrentWeakSet.add( myObject ); 

迭代

要访问集合中的元素:

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.
    }
}

去除

弱意味着不需要删除元素。随着元素被废弃和垃圾收集,它们从我们的集合(Map/Set)中消失。

于 2014-08-14T02:16:00.080 回答
5

文档中所述MapMaker不是泛型类型;它是<Object, Object>。这意味着您可以将任何内容作为键或值,您只需要在检索时进行转换。引用链接:

   ConcurrentMap<Request, Stopwatch> timers = new MapMaker()
       .concurrencyLevel(4)
       .weakKeys()
       .makeMap();

要获取条目,您只需Set调用.MapMap#entrySet()

于 2013-04-12T18:50:16.363 回答
1

您的原始方法可以正常工作,您只需将类型参数放在调用makeMap()

Set<Object> concurrentSet = Collections.newSetFromMap(
new MapMaker().weakKeys().<Object, Boolean> makeMap());

使用 Java 较少使用的泛型方法调用语法。 Java 规范

于 2015-08-04T11:09:29.320 回答