web-dev-qa-db-fra.com

Y a-t-il une softhashmap à Java?

Je sais qu'il y a un WeakHashMap dans Java.util, mais depuis qu'il utilise WeakReferences pour tout, ce qui est uniquement référencé par ce type Map, des objets référencés seront perdus au cycle de GC suivant. Il est donc presque inutile si vous souhaitez mettre en cache des données aléatoires, qui est très susceptible d'être demandée à nouveau sans être liée au reste du temps. La meilleure solution serait une carte qui utilise plutôt SoftReferences, mais je ne l'ai pas trouvée dans le Java RT.

62
tigger

Modifier (août 2012):

Il s'avère que la meilleure solution est probablement Guava 13.0's Cache classes, expliquée sur Wiki de Guava - C'est ce que je vais utiliser. Il supporte même la construction d'un SoftHashMap (voir CacheBuilder.newBuilder().softKeys()), mais ce n'est probablement pas ce que vous voulez, comme Java Expert Jeremy Manson explique (ci-dessous " ll trouver le lien).


Pas que Je sache (novembre 2008), mais vous trouverez une implémentation de SoftHashMap sur le net.

Comme celui-ci: SoftHashMap ou celui-ci .


Modifier (novembre 2009)
AS Matthias mentionne dans les commentaires, le Google Guava MapMaker Utilise Softreferences:

A ConcurrentMap constructeur, fournissant une combinaison de ces fonctionnalités:

  • clés douces ou faibles,
  • valeurs douces ou faibles,
  • expiration chronométrée, et
  • calcul à la demande des valeurs.

Comme mentionné dans Ce fil , un autre candidat JSR166Y:

jsr166y.concurrentRerenceFerenceHashMap

Il fournit une alternative carte de référence simultanée à la mise en œuvre de Google (qui repose sur un thread de fond aux entrées d'expulsion)


Edit (août 2012)

L'implémentation Google utilise un fil d'arrière-plan uniquement lorsque l'expiration chronométrée des entrées est demandée. En particulier, il utilise simplement Java.util.Timer, qui n'est pas si intrusif comme ayant un fil de fond séparé.

Jeremy Manson recommande, pour n'importe quel cache, à l'aide de cette fonctionnalité pour éviter les dangers de SofTreference: http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-a-clear_07.html

Il y a une autre mise en œuvre de Apache Commons , nommément org.apache.commons.collections.map.referencemap ; Il ne supporte pas le retrait chronométré, mais il prend en charge le choix de savoir si les clés doivent être comparées par l'identité ou par l'égalité. De plus, cette mise en œuvre n'est pas concurrente - elle peut être faite synchronisée, mais cela fonctionne moins bien sous des accès à partir de threads multiples.

28
VonC

Je connais deux bibliothèques qui offrent une implémentation de SoftHashMap:

  1. Apache Commons : org.apache.commons.collections.map.referencemap

  2. collections Google : com.google.common.collect.Referencemap

20
Gili

Il existe un exemple de mise en œuvre dans 98 problème de Java Bulletin d'information

4
jb.

Avez-vous envisagé d'utiliser un LRUMAP au lieu d'un hashmap souple? Vous obtenez plus de contrôle sur ce qui est stocké (ou au moins, combien).

2
Joel

Apache Shiro est livré avec une softhashmap conçu pour la mise en cache. Sa base sur l'article affiché par JB ci-dessus et sous licence sous Apache V2. Vous pouvez trouver la documentation ici et le code source ICI .

2
DallinDyer

Si vous souhaitez mettre en œuvre une cache Softreferences est définitivement une meilleure idée que les références faibles, mais il met toute votre politique d'élimination du cache entre les mains du collecteur des ordures. Ce qui n'est probablement pas ce que vous voulez.

Si la politique d'élimination du cache est importante, vous devrez le faire sur votre propre probabilité en utilisant des références régulières. Cependant, vous allez devoir décider quand éjecter des articles et pour éjecter. Si vous ne voulez que perdre des choses lorsque vous manquez d'espace de tas, vous pouvez interroger des espaces de démarrage disponibles via:

Runtime.getRuntime().getFreeMemory();

Ensuite, une fois que la mémoire libre tombe en dessous d'une certaine quantité, vous pouvez démarrer des éléments de dépose. Ou vous pouvez simplement implémenter une taille maximale pour le cache et utiliser cela pour décider quand déposer des choses.

voici un Cache LR J'ai conçu avec O(1) Insertion, Deletion et temps de recherche, comportant un nombre maximum configurable d'éléments. Si vous voulez un cache, ceci est va être une meilleure solution imho qu'un SoftHashMap.

Les softreférences sont un excellent moyen de créer un cache griffable. La solution idéale serait donc d'utiliser une softhashmap avec un cache de taille fixe régulière. Demandez à tous les insertions dans le cache d'entrer dans le cache fixe et de la carte de hachage logicielle, puis de référencer quelque chose, voyez simplement si c'est dans le hayonnage mou (et mettez à jour le temps de référence dans le cache). Ainsi, tous vos articles les plus importants (selon la stratégie choisie LRU, MFU, ...) ne seront jamais supprimés car ils sont désignés dans le cache, mais vous serez également conserver à plus de choses (sans contrôle de politique). comme il y a suffisamment de mémoire.

1
luke