SparseArray
peut être utilisé pour remplacer HashMap
lorsque la clé est de type primitif. Il existe quelques variantes pour différents types de clé / valeur, même si elles ne sont pas toutes disponibles publiquement.
Les avantages sont:
- Sans allocation
- Pas de boxe
Désavantages:
- Généralement plus lent, non indiqué pour les grandes collections
- Ils ne fonctionneront pas dans un projet non Android
HashMap
peut être remplacé par le texte suivant:
SparseArray <Integer, Object>
SparseBooleanArray <Integer, Boolean>
SparseIntArray <Integer, Integer>
SparseLongArray <Integer, Long>
LongSparseArray <Long, Object>
LongSparseLongArray <Long, Long> //this is not a public class
//but can be copied from Android source code
En termes de mémoire, voici un exemple de SparseIntArray
vs HashMap<Integer, Integer>
pour 1000 éléments:
SparseIntArray
:
class SparseIntArray {
int[] keys;
int[] values;
int size;
}
Classe = 12 + 3 * 4 = 24 octets
Tableau = 20 + 1000 * 4 = 4024 octets
Total = 8072 octets
HashMap
:
class HashMap<K, V> {
Entry<K, V>[] table;
Entry<K, V> forNull;
int size;
int modCount;
int threshold;
Set<K> keys
Set<Entry<K, V>> entries;
Collection<V> values;
}
Classe = 12 + 8 * 4 = 48 octets
Entrée = 32 + 16 + 16 = 64 octets
Tableau = 20 + 1000 * 64 = 64024 octets
Total = 64136 octets
Source: Android Memories par Romain Guy à partir de la diapositive 90.
Les nombres ci-dessus correspondent à la quantité de mémoire (en octets) allouée sur le tas par JVM. Ils peuvent varier en fonction de la JVM spécifique utilisée.
Le java.lang.instrument
package contient des méthodes utiles pour les opérations avancées telles que la vérification de la taille d'un objet avec getObjectSize(Object objectToSize)
.
Des informations supplémentaires sont disponibles dans la documentation officielle d' Oracle .
Classe = 12 octets + (n variables d'instance) * 4 octets
Tableau = 20 octets + (n éléments) * (taille de l'élément)
Entrée = 32 octets + (taille du 1er élément) + (taille du 2ème élément)
Je suis venu ici en voulant juste un exemple d'utilisation
SparseArray
. Ceci est une réponse supplémentaire à cela.Créer un SparseArray
A
SparseArray
mappe des entiers à certainsObject
, vous pouvez donc remplacerString
dans l'exemple ci-dessus par n'importe quel autreObject
. Si vous mappez des entiers à des entiers, utilisezSparseIntArray
.Ajouter ou mettre à jour des éléments
Utilisez
put
(ouappend
) pour ajouter des éléments au tableau.Notez que les
int
clés n'ont pas besoin d'être en ordre. Cela peut également être utilisé pour modifier la valeur d'uneint
clé particulière .Supprimer des éléments
Utilisez
remove
(oudelete
) pour supprimer des éléments du tableau.Le
int
paramètre est la clé entière.Rechercher des valeurs pour une clé int
Utilisez
get
pour obtenir la valeur d'une clé entière.Vous pouvez utiliser
get(int key, E valueIfKeyNotFound)
si vous souhaitez éviter d'obtenirnull
des clés manquantes.Itérer sur les éléments
Vous pouvez utiliser
keyAt
etvalueAt
certains index pour parcourir la collection car leSparseArray
maintient un index distinct distinct desint
clés.Notez que les clés sont classées par valeur croissante, et non dans l'ordre dans lequel elles ont été ajoutées.
la source
Ce n'est qu'un avertissement de cette documentation de ce tableau fragmenté:
Le
SparseArray
est fait pour être efficace en mémoire que l'utilisation du HashMap normal, c'est-à-dire qu'il n'autorise pas plusieurs espaces dans le tableau, contrairement à HashMap. Il n'y a rien à craindre, vous pouvez utiliser le HashMap traditionnel si vous ne souhaitez pas vous soucier de l'allocation de mémoire à l'appareil.la source
SparseArray
empêche l'entier clé d'être une boîte automatique, ce qui est une autre opération et des performances de coût. plutôt que de mapper, il renverra automatiquement l'entier primitif àInteger
Un tableau épars en Java est une structure de données qui mappe des clés à des valeurs. Même idée qu'une carte, mais implémentation différente:
Une carte est représentée en interne sous la forme d'un tableau de listes, où chaque élément de ces listes est une paire clé / valeur. La clé et la valeur sont toutes deux des instances d'objet.
Un tableau fragmenté est simplement constitué de deux tableaux: un tableau de clés (primitives) et un tableau de valeurs (objets). Il peut y avoir des lacunes dans ces indices de tableaux, d'où le terme tableau «clairsemé».
L'intérêt principal du SparseArray est qu'il économise de la mémoire en utilisant des primitives au lieu d'objets comme clé.
la source
Après quelques recherches sur Google, j'essaye d'ajouter des informations aux réponses déjà publiées:
Isaac Taylor a fait une comparaison des performances pour SparseArrays et Hashmaps. Il affirme que
et
Une comparaison sur Edgblog montre qu'un SparseArray nécessite beaucoup moins de mémoire qu'un HashMap en raison de la plus petite clé (int vs Integer) et du fait que
En conclusion, je dirais que la différence pourrait être importante si vous allez stocker beaucoup de données dans votre carte. Sinon, ignorez simplement l'avertissement.
la source
Oui c'est vrai. Mais lorsque vous n'avez que 10 ou 20 éléments, la différence de performance devrait être insignifiante.
Je pense que le plus souvent, nous utilisons uniquement
HashMap
pour rechercher une valeur associée à une clé alors queSparseArray
c'est vraiment bon pour cela.Le code source de SparseArray est assez simple et facile à comprendre, de sorte que vous ne payez que peu d'efforts pour le déplacer vers d'autres plates-formes (via un simple COPY & Paste).
Tout ce que je peux dire, c'est (à la plupart des développeurs) qui s'en soucient?
Un autre aspect important de
SparseArray
est qu'il utilise uniquement un tableau pour stocker tous les éléments pendant l'HashMap
utilisationEntry
, doncSparseArray
coûte beaucoup moins de mémoire qu'unHashMap
, voir cecila source
Il est malheureux que le compilateur émette un avertissement. Je suppose que HashMap a été largement utilisé pour stocker des éléments.
Les SparseArrays ont leur place. Étant donné qu'ils utilisent un algorithme de recherche binaire pour trouver une valeur dans un tableau, vous devez considérer ce que vous faites. La recherche binaire est O (log n) tandis que la recherche de hachage est O (1). Cela ne signifie pas nécessairement que la recherche binaire est plus lente pour un ensemble de données donné. Cependant, à mesure que le nombre d'entrées augmente, la puissance de la table de hachage prend le dessus. D'où les commentaires où un faible nombre d'entrées peut être égal et peut-être mieux que d'utiliser un HashMap.
Un HashMap n'est aussi bon que le hachage et peut également être affecté par le facteur de charge (je pense que dans les versions ultérieures, ils ignorent le facteur de charge afin qu'il puisse être mieux optimisé). Ils ont également ajouté un hachage secondaire pour s'assurer que le hachage est bon. Aussi la raison pour laquelle SparseArray fonctionne très bien pour relativement peu d'entrées (<100).
Je suggérerais que si vous avez besoin d'une table de hachage et que vous voulez une meilleure utilisation de la mémoire pour les entiers primitifs (pas de boxing automatique), etc., essayez trove. ( http://trove.starlight-systems.com - licence LGPL). (Aucune affiliation avec trove, tout comme leur bibliothèque)
Avec le bâtiment multi-dex simplifié que nous avons, vous n'avez même pas besoin de reconditionner pour ce dont vous avez besoin. (trove a beaucoup de classes)
la source