J'ai un problème similaire à celui discuté here, mais avec une utilisation pratique plus forte.Accès getEntry caché (clé d'objet) dans HashMap
Par exemple, j'ai un Map<String, Integer>
, et j'ai une fonction, qui est donné une clé et dans le cas où la valeur entière cartographié est négatif, met NULL
à la carte:
Map<String, Integer> map = new HashMap<String, Integer>();
public void nullifyIfNegative(String key) {
Integer value = map.get(key);
if (value != null && value.intValue() < 0) {
map.put(key, null);
}
}
I ce cas, la recherche (et donc, hashCode
calcul pour la clé) est fait deux fois: un pour la recherche et un pour le remplacement. Il serait agréable d'avoir une autre méthode (qui est déjà en HashMap
) et permet de rendre plus efficace:
public void nullifyIfNegative(String key) {
Map.Entry<String, Integer> entry = map.getEntry(key);
if (entry != null && entry.getValue().intValue() < 0) {
entry.setValue(null);
}
}
Les cas mêmes préoccupations, lorsque vous voulez manipuler des objets immuables, qui peuvent être des valeurs de carte:
Map<String, String>
: Je souhaite ajouter quelque chose à la valeur de chaîne.Map<String, int[]>
: Je souhaite insérer un nombre dans le tableau.
Ainsi, le cas est assez commun. Solutions qui pourraient fonctionner, mais pas pour moi:
- Réflexion. Est bon, mais je ne peux pas sacrifier la performance juste pour cette belle fonctionnalité.
- Utilisez
org.apache.commons.collections.map.AbstractHashedMap
(il a au moins la méthodeprotected getEntry()
), mais malheureusement, les collections-communes ne supportent pas les génériques. - , mais cette bibliothèque (AFAIK) est obsolète (non synchronisée avec la dernière version de bibliothèque d'Apache) et (ce qui est critique) n'est pas disponible dans le référentiel central maven.
- Utilisez des wrappers de valeur, ce qui signifie "making values mutable" (par exemple, utilisez des entiers mutables [par exemple
org.apache.commons.lang.mutable.MutableInt
] ou des collections au lieu de tableaux). Cette solution conduit à la perte de mémoire, que je voudrais éviter. - Essayez d'étendre
java.util.HashMap
avec la mise en œuvre de classe personnalisée (qui devrait être dans le paquetjava.util
) et le mettre à endorsed folder (commejava.lang.ClassLoader
refusera de le charger dansClass<?> defineClass(String name, byte[] b, int off, int len)
, voir les sources), mais je ne veux pas patcher JDK et ressemble à la liste des paquets qui peuvent être approuvés, n'inclut pasjava.util
.
La question similaire est déjà soulevée sur sun.com bugtracker, mais je voudrais savoir, quelle est l'opinion de la communauté et ce qui peut être la sortie prendre à l'esprit la mémoire maximale & l'efficacité du rendement.
Si vous êtes d'accord, c'est une fonctionnalité agréable et bénéficiaire, s'il vous plaît, votez ce bug!
@sfussenegger Merci pour la réponse, mais créer des wrappers d'objets n'est pas un bon choix pour moi. Je veux atteindre des performances maximales avec un impact mémoire minime. –
@dma_k Si je me souviens bien, l'impact mémoire d'un tableau de longueur 1 est de 4 octets (alors qu'un objet encapsuleur serait de 12 octets par instance). Donc (ab) en utilisant de tels tableaux c'est à peu près la même chose que de travailler avec des pointeurs en C - et vous n'appelez pas les pointeurs inefficaces, n'est-ce pas? ;) – sfussenegger
Je m'attendrais à ce que la taille du tableau soit '4 [= longueur] +4 [= int_size] * longueur (array) + 8_byte_align' (je peux me tromper). Donc, 'int [1]' allouera 8 octets, 'int [2]' - 16 octets :) –