Паралелен набор със слаби препратки и хеш на самоличността

Исках едновременен набор със слаби препратки към елементи. Мислех да направя това с помощта на MapMaker на Guava:

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());
                            ^

Някакви решения как мога да получа паралелен набор със слаби препратки към елементи?


person r.v    schedule 12.04.2013    source източник


Отговори (3)


Както е обяснено в документацията , MapMaker не е общ тип; това е <Object, Object>. Това означава, че можете да поставите всичко като ключ или стойност, просто трябва да го изпълните, когато извличате. Цитирам линка:

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

За да получите Set с Map записите, просто извикайте Map#entrySet().

person m0skit0    schedule 12.04.2013
comment
Исках паралелен комплект. Как да взема комплект от него тогава? - person r.v; 12.04.2013
comment
makeMap() е общ, така че ConcurrentMap<K, V> timers = new MapMaker() .concurrencyLevel(4) .weakKeys() .makeMap(); ще работи. - person Xaerxess; 12.04.2013
comment
@Xaerxess не забеляза, че цитатът премахна XML таговете :) Форматирах го като код, благодаря. - person m0skit0; 12.04.2013
comment
Все още искате Collections.newSetFromMap, както е илюстрирано в първоначалния въпрос. - person Kevin Bourrillion; 13.04.2013

За да изясня кода, намекнат в приетия отговор и коментарите, ето моя собствен поглед върху кода, за да получа едновременен слаб набор.

Java, без Guava

Използвайки идиома, предложен в документацията на класа, използвайте Collections.newSetFromMap за обвиване на едновременна карта като набор. Използването на Boolean като тип стойност на картата е само пълнител, без значение.

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, заместваме WeakHashMap с карта от Google Guava ="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/MapMaker.html" rel="nofollow noreferrer">MapMaker според предложението на Guava doc за обадете се на new MapMaker().weakKeys().makeMap(). Документът на 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.
    }
}

Да премахна

Да си слаб означава, че няма нужда да премахваш елементи. Тъй като елементите стават неизползвани и се събират на боклук, те изчезват от нашата колекция (карта/комплект).

person Basil Bourque    schedule 14.08.2014

Вашият оригинален подход ще работи добре, просто трябва да поставите параметрите на типа си в извикването на makeMap()

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

използвайки по-малко използвания генеричен синтаксис за извикване на метод на Java. Спецификация на Java.

person Stuart    schedule 04.08.2015