71 votes

Existe-t-il un SoftHashMap en Java ?

Je sais qu'il y a WeakHashMap en java.util mais comme il utilise WeakReference pour tout, qui n'est référencé que par cette Map Les objets référencés seront perdus lors du prochain cycle GC. C'est donc presque inutile si vous voulez mettre en cache des données aléatoires, qui sont très susceptibles d'être demandées à nouveau sans être liées durablement le reste du temps. La meilleure solution serait une carte, qui utilise SoftReference à la place, mais je n'en ai pas trouvé dans le paquet Java RT.

32voto

VonC Points 414372

Edit (août 2012) :

Il s'avère qu'actuellement, la meilleure solution est probablement celle de Guava 13.0. Cache classes, expliquées sur Wiki de la Goyave - c'est ce que je vais utiliser. Il permet même de construire un SoftHashMap (voir CacheBuilder.newBuilder().softKeys() ), mais ce n'est probablement pas ce que vous voulez, comme l'explique l'expert Java Jeremy Manson (vous trouverez le lien ci-dessous).


Pas que Je connais (Nov. 2008), mais vous pouvez trouver une certaine mise en œuvre de SoftHashMap sur le net.

Comme celui-là : SoftHashMap o celui-ci .


Edit (Nov. 2009)
Comme Matthias mentionne dans les commentaires, le Google Guava MapMaker utilise les SoftReferences :

A ConcurrentMap constructeur, offrant toute combinaison de ces caractéristiques :

  • les touches programmables ou faibles,
  • des valeurs molles ou faibles,
  • l'expiration programmée, et
  • le calcul des valeurs à la demande.

Comme mentionné dans ce fil un autre candidat JSR166y :

jsr166y.ConcurrentReferenceHashMap (carte de hachage)

Il fournit une carte de référence concurrente à l'implémentation de Google (qui s'appuie sur un thread d'arrière-plan pour évincer les entrées).


Edit (août 2012)

L'implémentation de Google utilise un thread d'arrière-plan uniquement lorsque l'expiration programmée des entrées est demandée. En particulier, elle utilise simplement java.util.Timer ce qui n'est pas aussi gênant que d'avoir un fil de fond séparé.

Jeremy Manson recommande, pour tout cache, d'utiliser cette fonctionnalité pour éviter les dangers de SoftReference : http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html

Il existe une autre implémentation de Apache Commons à savoir org.apache.commons.collections.map.ReferenceMap elle ne supporte pas la suppression temporisée, mais elle permet de choisir si les clés doivent être comparées par identité ou par égalité. De plus, cette implémentation n'est pas concurrente - elle peut être rendue synchronisée, mais cela fonctionne moins bien avec des accès provenant de plusieurs threads.

0 votes

Une autre implémentation utile est celle d'OpenJDK. sun.security.util.Cache qui supporte une taille maximale, une durée de vie limitée dans le temps, et un choix de références normales contre des SoftReferences. La version de Java 7 fait correspondre les objets aux objets ; la version de Java 8 est générique. Il est évident que nous ne devrions pas importer sun. directement, mais le code est sous licence GPL et peut être copié si vous voulez un point de départ.

22voto

Gili Points 14674

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

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

  2. Collections Google : com.google.common.collect.ReferenceMap

3 votes

ReferenceMap a été supprimé de Google Collections. Utilisez MapMaker maintenant.

4voto

jb. Points 4932

Il existe un exemple de mise en œuvre dans le numéro 98 de la lettre d'information des spécialistes de Java

1 votes

J'utilise la version 98 de la SoftHashMap du Dr Kabutz dans un projet depuis près de six ans et elle a bien fonctionné pour cet usage particulier. Cela semble un peu long à coller ici, mais vous pouvez trouver un exemple dans jidesoft.swing.SoftHashMap et org.jvnet.substance.utils.SoftHashMap. Il existe une version modifiée dans org.pushingpixels.substance.internal.utils.SoftHashMap.

2voto

Joel Points 11003

Avez-vous envisagé d'utiliser un LRUMap au lieu d'un HashMap souple ? Vous avez un meilleur contrôle sur ce qui est stocké (ou du moins, sur la quantité).

1 votes

LRU est l'approche valide de la vieille école. Mais un cache de référence douce devrait faire un meilleur travail d'adaptation aux pics et aux creux dans l'utilisation du cache et de la mémoire. C'est probablement la raison pour laquelle le PO demandait un analogue de SoftReference de WeakReferenceMap en premier lieu.

1voto

luke Points 6688

Si vous voulez implémenter un cache, les références souples sont définitivement une meilleure idée que les références faibles, mais cela met toute votre politique de suppression du cache entre les mains du ramasseur de déchets, ce qui n'est probablement pas ce que vous voulez.

Si la politique de suppression du cache est importante, vous devrez le faire vous-même, probablement en utilisant des références régulières. Cependant, vous allez devoir décider quand éjecter des objets et lesquels éjecter. Si vous ne voulez perdre des éléments que lorsque vous manquez d'espace dans le tas, vous pouvez demander l'espace disponible dans le tas via :

Runtime.getRuntime().getFreeMemory();

Ensuite, une fois que la mémoire libre passe en dessous d'un certain seuil, vous pouvez commencer à laisser tomber des objets. Ou vous pourriez simplement implémenter une taille maximale pour le cache et l'utiliser pour décider quand abandonner des éléments.

voici un Cache LRU i conçu avec un temps d'insertion, de suppression et de consultation de O(1), et dont le nombre maximal d'éléments est configurable. Si vous voulez un cache, ce sera une meilleure solution qu'une SoftHashMap.

Les softtreferences sont un excellent moyen de créer un cache évolutif. Ainsi, la solution idéale serait d'utiliser une SoftHashMap en même temps qu'un cache régulier de taille fixe. Toutes les insertions dans le cache vont à la fois dans le cache fixe et dans la SoftHashMap, puis pour référencer quelque chose, il suffit de voir si c'est dans la SoftHashMap (et de mettre à jour le temps de référence dans le cache). De cette façon, tous vos éléments les plus importants (selon la politique que vous avez choisie LRU, MFU, ...) ne seront jamais supprimés parce qu'ils sont référencés dans le cache, mais vous pourrez également conserver plus de choses (sans contrôle de la politique) tant qu'il y a suffisamment de mémoire.

1 votes

Comme l'explique Jeremy Manson, la suppression programmée (de MapMaker) est une bonne solution aux problèmes des SoftReferences : jeremymanson.blogspot.de/2009/07/ Sinon, Apache Commons maintient une implémentation de LRUMap, mentionnée ci-dessous par Joel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X