web-dev-qa-db-fra.com

SparseArray, vérifiez si la clé existe

J'implémentais un cache Bitmap à l'aide d'un HashMap<Integer, Bitmap> Et j'ai reçu l'avertissement suivant dans Eclipse:

Utilisez plutôt un nouveau SparseArray (...) pour de meilleures performances.

Je n'ai jamais entendu parler de cette classe auparavant, mais en l'inspectant, elle ne semble pas avoir de méthode containsKey() que j'appelais lors de la récupération d'un bitmap du cache pour vérifier s'il existe dans le cache, et si ce n'est pas le cas, ajoutez-le.

Des idées sur la meilleure façon de vérifier si la clé existe déjà?

Je suppose que je pourrais changer le code pour utiliser cette surcharge et vérifier null?

Bitmap bitmap = cache.get(key, null); 
41
magritte

Vous pouvez utiliser:

Bitmap bitmap = cache.get(key, null); 

Mais comprenez que c'est la même chose que get(key) :

Bitmap bitmap = cache.get(key); 

La meilleure façon d'utiliser get(key, default) est de fournir un cas générique par défaut, quelque chose à est un substitut valide lorsque la clé n'est pas trouvée .

Mais il n'y a aucune bonne raison de ne pas utiliser if(get(key) != null) comme remplacement rapide de contains().

47
Sam

Par conséquent, votre valeur peut être nulle dans diverses situations, je vous suggère d'utiliserindexOfKey(int key) Voici la référence indexOfKey (int key) .

Ensuite, vérifiez simplement la valeur de retour négative

if(mySparseArray.indexOfKey(int) < 0) {
   //Item does not exist. Do something relevant 
}
31
Alex

En partant de l'implémentation de SparseArray, il semble contre-intuitif qu'il puisse avoir de meilleures performances (complexité temporelle) que HashMap (autre que l'espace requis inférieur qui fait sens pour un environnement mobile) puisque le membre get () de SparseArray utilise binaire- recherche (O (log N)) tandis que pour HashMap utilise l'indexation de tableau (O (1)).

Fournir l'implémentation de la méthode get () pour les deux classes (en l'état):

public V get(Object key) { // for HashMap
    if (key == null)
        return getForNullKey();
    int hash = hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
            e != null;
            e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
            return e.value;
    }
    return null;
}

public E get(int key, E valueIfKeyNotFound) {  //for SparseArray
    int i = binarySearch(mKeys, 0, mSize, key);

    if (i < 0 || mValues[i] == DELETED) {
        return valueIfKeyNotFound;
    } else {
        return (E) mValues[i];
    }
}

quant à l'opportunité d'utiliser indexOfKey (key) <0 ou get (key) == null pour vérifier l'existence de la clé dans un SparseArray, tout va bien puisque les deux utilisent la recherche binaire en dessous.

public int indexOfKey(int key) {  // for SparseArray
    if (mGarbage) {
        gc();
    }

    return binarySearch(mKeys, 0, mSize, key);
}
1
neel

Citant de documentation .

SparseArrays mappe des entiers aux objets. Contrairement à un tableau normal d'objets, il peut y avoir des lacunes dans les indices. Il est destiné à être plus efficace que l'utilisation d'un HashMap pour mapper des entiers à des objets.

Vous pouvez utiliser get (int) qui retournerait également null si la clé n'est pas trouvée. Comme;

Bitmap bitmap = cache.get (clé);

1
auselen

Plusieurs façons:

  1. Si vous souhaitez quand même utiliser la valeur associée à la clé, vous pouvez utiliser get():

    val sparseArray = SparseArray<String>()
    val someKey = 123
    val someValue: String? = sparseArray[someKey]
    if(someValue!=null){
        //do something
    }
    

Notez que contrairement à ce que pense le IDE, il peut être nul, c'est pourquoi j'ai ajouté ?.

  1. si vous voulez juste vérifier s'il existe, vous pouvez utiliser indexOfKey(key) >= 0

  2. Si vous n'aimez pas ce qui précède et que vous voulez une option plus lisible, vous pouvez utiliser containsKey de la dépendance ktx-collection:

    implementation 'androidx.core:core-ktx:#'
    implementation 'androidx.collection:collection-ktx:#'
    

Usage:

    val sparseArray = SparseArray<String>()
    val someKey = 123
    if (sparseArray.containsKey(someKey)) {
        //do something
    }
0